0

I have a Shell Script file name TestLog.sh Inside I have a variable assigned with some value inside IF condition. I want to access that variable outside IF condition in the same file.

#!/bin/sh

sudo su <<EOF
if [ $# -eq 0 ]; then
LOG_LOCATION="Base/reports/jtl_logs"
CSV_LOCATION="Base/reports/csv"
LOOP_COUNT=30
elif [ $# -eq 1 ]; then
LOG_LOCATION="Base/reports/$1/jtl_logs"
CSV_LOCATION="Base/reports/$1/csv"
LOOP_COUNT=30
elif [ $# -eq 2 ]; then
LOG_LOCATION="Base/reports/$1/jtl_logs"
CSV_LOCATION="Base/reports/$1/csv"
LOOP_COUNT=$2
fi

echo $LOG_LOCATION
echo $CSV_LOCATION
echo $LOOP_COUNT
EOF

I call my script as

TestLog.sh 19.10.11 3

Expected Output:

Base/reports/19.10.11/jtl_logs
Base/reports/19.10.11/csv
3

Actual Output:

Display nothing

1 Answers1

1
sudo su <<EOF

The expansion of the variables inside here document with unquoted "limit string" (the <<EOF part) happens before the sudo command is executed.

a=1
sudo <<EOF
a=2
echo $a
EOF

The $a above is expanded first, so first it looks like:

sudo <<'EOF'
a=2
echo 1
EOF

then sudo command is run with the input.

You can force the shell not to expand the variables inside the here document by quoting the limit string. As I showed above with <<'EOF'. If the limit string is quoted, no expansion happens inside, the text is taken as it is. But that would make you jump into another problem - the $# will be 0 inside sudo, cause you didn't pass any parameters.

Also sudo su makes no sense. Just sudo or just su.

One solution could be such a construct:

sudo sh -c '
if [ $# -eq 0 ]; then
  LOG_LOCATION="Base/reports/jtl_logs"
  CSV_LOCATION="Base/reports/csv"
  LOOP_COUNT=30
elif [ $# -eq 1 ]; then
  LOG_LOCATION="Base/reports/$1/jtl_logs"
  CSV_LOCATION="Base/reports/$1/csv"
  LOOP_COUNT=30
elif [ $# -eq 2 ]; then
  LOG_LOCATION="Base/reports/$1/jtl_logs"
  CSV_LOCATION="Base/reports/$1/csv"
  LOOP_COUNT=$2
fi

echo $LOG_LOCATION
echo $CSV_LOCATION
echo $LOOP_COUNT
' -- "$@"

You can run a shell inside sudo and pass the script using -c option and specify the arguments to the shell. The quoting get's really hard, as you are inside quotes.

Alternatively and safer, you could create a temporary file, run it and remove it after your script execution. This let's you a bit more control.

cat >/tmp/tempfile.sh <<'EOF'
#!/bin/sh
if [ $# -eq 0 ]; then
  LOG_LOCATION="Base/reports/jtl_logs"
  CSV_LOCATION="Base/reports/csv"
  LOOP_COUNT=30
elif [ $# -eq 1 ]; then
  LOG_LOCATION="Base/reports/$1/jtl_logs"
  CSV_LOCATION="Base/reports/$1/csv"
  LOOP_COUNT=30
elif [ $# -eq 2 ]; then
  LOG_LOCATION="Base/reports/$1/jtl_logs"
  CSV_LOCATION="Base/reports/$1/csv"
  LOOP_COUNT=$2
fi

echo $LOG_LOCATION
echo $CSV_LOCATION
echo $LOOP_COUNT
EOF

sudo sh /tmp/tempfile.sh "$@"

rm /tmp/tempfile.sh

Or you could well pass the parameters to what you have now by specifying the input script for shell to be stdin:

sudo sh /dev/stdin "$@" <<'EOF'
if [ $# -eq 0 ]; then
LOG_LOCATION="Base/reports/jtl_logs"
CSV_LOCATION="Base/reports/csv"
LOOP_COUNT=30
elif [ $# -eq 1 ]; then
LOG_LOCATION="Base/reports/$1/jtl_logs"
CSV_LOCATION="Base/reports/$1/csv"
LOOP_COUNT=30
elif [ $# -eq 2 ]; then
LOG_LOCATION="Base/reports/$1/jtl_logs"
CSV_LOCATION="Base/reports/$1/csv"
LOOP_COUNT=$2
fi

echo $LOG_LOCATION
echo $CSV_LOCATION
echo $LOOP_COUNT
EOF

I don't like all three options specified above. Running such long scripts under sudo feels very unsafe. All the ifs inside sudo look strange - why would you check the $# inside sudo? Why not do it in parent shell and only pass parsed variables to the command you only need to run via sudo? This feels like it violates a lot of least privilege principle - the ifs nor the echos, they doesn't need to be run as root at all.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111