Reputation: 473
I'm trying to remote login to a shell and execute a bunch of commands on the shell. But to make it more readable, I'd like to place my code over multiple lines. How should I be doing this?
ssh -o <Option> -x -l <user> <host> " $long_command1; $long_command2; .... "
Thanks!
Upvotes: 35
Views: 40131
Reputation: 295707
The answers thus far have all left out a technique that's much less issue-prone than writing code in a heredoc, quoted string, or other environment that has subtly different behavior than the outer shell: Define a function, and let bash itself serialize that function into the arguments passed to ssh.
remoteFunc() {
long_command 1 && ...
long_command 2...
if blah; then long_command 3; else meh; fi
# In a single-quoted string, these quotes would disappear!
echo "string with 'single quotes'"
# in a heredoc or double quotes, remoteCommand would be run locally!
remoteCmdOutput=$(remoteCommand)
}
ssh remoteHost "$(declare -f remoteFunc); remoteFunc"
If your function requires variables to also be passed over ssh, you can use declare -p
to serialize them the same way:
myVar='...whatever...'
myOtherVar='...same...'
myFunc() {
echo "Do something with $myVar and $myOtherVar here..."
}
ssh remoteHost "$(declare -f myFunc); $(declare -p myVar myOtherVar); myFunc"
Upvotes: 1
Reputation: 849
This works on Ubuntu 24.04 host and server
Some of these came from other answers on SO and on other sites. I did have to play with those answers until it worked as I needed it:
my_cool_sudo_password <= ensure there is newline after this
sudo su -
\|
in required (it's not a markdown for SO posts).cat secure_sudo_pwd - << EOF | ssh $your_userid@$your_remote_host cat \| sudo --prompt="" -S -- su -
hostname
whoami
# echo commented out line
hostname
whoami
echo line1
EOF
typical output:
vm-1 <= my host is a virtualbox running Ubuntu 24.04
root <= confirms that it is running as root
root
vm-1
line1
I have checked as best as I can whether the password or content of this SSH session shows up on the host:
# on the host
cd /var/log
tail -f dmesg syslog auth.log kern.log
There were no indications of "sudo", "hostname", "whoami", or password, etc.
There was an entry in authlog showing an ssh login
Jan 7 12:55:06 vm-1 sshd[12122]: Accepted publickey for xx from 10.0.0.xx port 33698 ssh2: ED25519 SHA256:U24xx
Upvotes: 0
Reputation: 2314
You can use the Here Documents
feature of bash
.
It is like:
ssh <remote-host> bash <<EOF
echo first command
echo second command
EOF
EOF marks the end of the input.
For further info: use man bash
and search for Here Documents
.
Edit: The only caveat is that using variables can be tricky, you have to escape the $
to protect them to be evaluated on the remote host rather then the local shell. Like \$HOSTNAME
. Otherwise works with everything that is run from bash and uses stdin
.
Upvotes: 34
Reputation: 59556
ssh
is in fact just passing a string to the remote host. There this string is given to a shell which is supposed to interpret it (the user's login shell, which is typically something like bash
). So whatever you want to execute needs to be interpretable by that remote login shell, that's the whole rule you have to stick to.
You can indeed just use newlines within the command string:
ssh alfe@sweethome "
ls /home/alfe/whatever
ping foreignhost
date
rm foobar
"
Upvotes: 53
Reputation: 6297
You can do like in the following example.
ssh -o <Option> -x -l <user> <host> '
pwd
whoami
ls
echo "$PATH"
'
Upvotes: 3