- Published on
Shell: Execute commands on remote machine - 101 Guide
What
I have seen so many different ways on how to execute the commands in remote machine, that I thought it's worth having a centralised place for all of them explaing pros and cons.
Options
There are a lot of caveats about executing remote commands, as well as the end results you are trying to achieve. I will focus on the 2 main ones, which should over 90% of the cases.
Cases:
- Gather information from remote machine and use it in your local script.
- Just run the tasks on remote machine, and don't worry about output.
Few things to note in advance:
sshpass
is used instead ofssh
to avoid need to type in password (helps to achieve fully automated process)StrictHostKeyChecking=no
is used to avoid the need to grant access to ssh on first usage (otherwise you will be asked to type in yes when you run ssh for the first time to unknown host)- VM_USER, VM_IP, and VM_PASSWORD are here to simplify examples.
Set the scene
Task
Print 1-10 on the screen on new lines.
Option 1. Pass it as part of SSH
######## One Liner:
sshpass -p "$VM_PASSWORD" ssh -o StrictHostKeyChecking=no $VM_USER@$VM_IP i=0 && while [ $i -le 10 ]; do echo "It is: $i" && ((i=i+1)); done
######## Using EOF
sshpass -p "$VM_PASSWORD" ssh -o StrictHostKeyChecking=no $VM_USER@$VM_IP << EOF
i=0
while [ \$i -le 10 ]
do
echo "It is: \$i"
((i=i+1))
done
EOF
Option 2. Create separate script
- Create new file
touch test.sh && nano test.sh && chmod +x test.sh
- Update
test.sh
to contain code you want to execute
while [ $i -le 10 ]
do
echo "It is: $i"
((i=i+1))
done
- Send the file to host machine and execute it.
sshpass -p "$VM_PASSWORD" rsync -av test.sh $VM_USER@$VM_IP:~/test.sh
i=0
sshpass -p "$VM_PASSWORD" ssh -o StrictHostKeyChecking=no $VM_USER@$VM_IP << EOF
export i=$i # Here you are setting remote variable 'i' to the value of internal $i, or 0 if that is not set
./test.sh
####### Pros/Cons
Type | Pros | Cons |
---|---|---|
One liner pass it aspart of SSH | Short Works well for 1 command | Gets extremely complicated if you are trying to do more then 1 command |
Pass it as part of SSH using EOF | Much more readable then one liner No need to use && constantly | You need to be aware of escaping $ signs (use $) to avoid using your environment values Impossible to test without executing parent script once your code gets complicated |
Create file, send the file to VM and execute it | Single responsibility script You stick with proper development experience Can test in remote at any time | When you get tens of 'single responsibiity' scripts, you end-up flooding your repository, so it gets hard to manage your scripts |
Conclusions
As everything in this word, there is no best or worst, and it depends on your situation. From my past experience I would definitely strongly suggest sending separate scripts to your remote machine and executing them with idea of single responsibility
scripts.
But have a read again at pros and cons, decide which one to go with, and stick with it!
Good luck bashing!