I am trying to create a file using bash script. Here is the function that I am using.
function create_service_file() {
# create service file
echo "Creating service file /etc/systemd/system/${SERVICE_NAME}"
cat <<- EOF | sudo tee /etc/systemd/system/${SERVICE_NAME}
[Unit]
Description=$DESCRIPTION
After=syslog.target network.target
[Service]
User=$USER
WorkingDirectory=${WORKING_DIRECTORY}
ExecStart=${JAVA_HOME}/bin/java -jar ${JAR_FILE}
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143
Restart=always
RestartSec=30s
[Install]
WantedBy=multi-user.target
EOF
echo "/etc/systemd/system/${SERVICE_NAME} file has been written successfully"
}
When I run the script. It asks me for password at line cat <<- EOF | sudo tee /etc/systemd/system/${SERVICE_NAME}
After entering the password, it writes the file.
If I check in the directory there is a file
Now instead of giving password from the command I want to run this command directly. In other parts of the script. I am using the following syntax to achieve this thing
local is_service_failed=$(sudo -S <<< "${PASSWORD}" systemctl is-active $service)
or
sudo -S <<< "${PASSWORD}" systemctl start $service
These commands works fine. But now when I am trying to use the same thing it is not working. cat <<- EOF | sudo -S <<< ${PASSWORD} tee /etc/systemd/system/${SERVICE_NAME}
File is creating but nothing is written inside the file.
What am I doing wrong? How can I make it work.
You can't redirect standard input twice to to the same command. Either it reads the password from standard input, or it reads the here document on standard input. It can't do both.
You can use a subshell to separate the two:
sudo -S <<<"$password" bash -c 'tee /etc/systemd/system/$1 <<EOF
.... your here document
EOF
' -s "SERVICE_NAME"
If you need literal single quotes inside the here document, a common solution is to use what I like to call "seesaw quoting". A single-quoted string immediately adjacent to a double-quoted string containing a literal single quote are joined by the shell into a single string with a single quote in it.
sudo -S <<<"$password" bash -c 'tee /etc/systemd/system/$1 <<EOF
[Service]
ExecStart=echo "You don'"'"'t say"
EOF
' -s "SERVICE_NAME"
You might need a double take on that. That's a single-quoted string bash -c '... echo "You don'
adjacent to the double-quoted string "'"
adjacent to the single-quoted string 't say"...'
.
Perhaps notice also how this avoids the useless use of cat
. sudo
can perfectly read standard input from a here document (and doesn't even know that it's coming from one; the shell takes care of all of this).
Anyway, as noted in comments, you really really want to avoid embedding your password in a script. Set up sudo
with NOPASSWD
or run the script as root
in the first place (or avoid requiring root
privileges if you can).