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 if
s 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 if
s nor the echo
s, they doesn't need to be run as root at all.