If you use multi-line then the separator is a newline and you don't need an extra semicolon.
The for host in `cat hostlist` splits at "whitespace" (space,tab,newline, which is by default in "$IFS"), and is subject to filename generation (expansion of wildcards). Fine if you trust it.
If you have one host per line, then you can use a rock-solid
while read -r host junk <&3
do
...
done 3< hostlist
The read by default reads one line and ignores a leading space. The purpose of the junk variable is to also ignore a trailing space.
One more question:
Once I ssh into a server, If I want to perform a conditional check (like an IF clause) for the existence of /app/version/pkms7c directory, only then execute below cp, mv and ln commands. Would that be possible in the below construct ?
I think I will have to make it a script ie. a script containing IF... statement plus cp, mv and ln commands. Right ?
If you know the login shell at the remote is bash then you can do bash syntax. Also, the remote script is in " " quotes to allow local substitutions like $host.
The following works:
ssh -n "johndoe@$host" "
if [ -d /app/version/pkms7c ]
then
cp /app/version/pkms7c/config.prm /nfs_server83/backups/config_backup.prm_$host
mv /app/version/pkms7c/config.prm /shared_fs2/app_configs/pkms
ln -s /shared_fs2/app_configs/pkms/config.prm /app/version/pkms7c/config.prm
fi
"
But if you want to do more things, like having a remote $dir, then you must go for the safe method:
while read -r host junk <&3
do
echo "Currently running commands on $host ...."
ssh "johndoe@$host" /bin/bash -s "$host" << "_EORS_"
#!/bin/bash
# Positional parameters (passed to /bin/bash)
host=$1
# Other variables
dir=/app/version/pkms7c
if [ -d "$dir" ]
then
cp "$dir"/config.prm /nfs_server83/backups/config_backup.prm_$host
mv "$dir"/config.prm /shared_fs2/app_configs/pkms
ln -s /shared_fs2/app_configs/pkms/config.prm /app/version/pkms7c/config.prm
fi
_EORS_
# EndOfRemoteScript
done 3< hostlist
The remote script is in a here document. Of course a separate file would work as well.
It is passed through the ssh to the remote /bin/bash (no ssh -n that would prevent this). bash -s means the script comes from stdin not the first argument. Instead the first argument becomes $1 (the 1st positional parameter).
You will find it much easier then scripts in loops with easier error handling as stack does it for you on basic level
There is also a lot of done code in the wild as ansible is defacto standard to manage many types of devices.