Running a file on remote server by ssh respecting shebang line - shell

So I have a file. Currently it looks like this:
#!/usr/bin/env python3
print(1)
I want to tun it on remote machine. The easy way to do this is to run
< test.py ssh server-name python3
But what if I don't know that it's a python script (or I may not know that it's python3 not python2) and want to respect its shebang?
I tried
< test.py ssh server-name exec /dev/stdin
But it fails since /dev/stdin is not executable
For simplicity let's assume both of the servers are latest Ubuntu.
So the question is how to run arbitrary script respecting it shebang?

It's the OS that uses the shebang line: see your execve(2) man page. The script file must be executable, residing on the system.
You can extract it from the script to use on the remote side: untested:
shebang=$(sed -n '1 {s/^#!//p; q}' test.py)
ssh server-name "$shebang -" < test.py

Related

Script to copy data from cluster local to pod is neither working nor giving any error

The bash script I'm trying to run on the K8S cluster node from a proxy server is as below:
#!/usr/bin/bash
cd /home/ec2-user/PVs/clear-nginx-deployment
for file in $(ls)
do
kubectl -n migration cp $file clear-nginx-deployment-d6f5bc55c-sc92s:/var/www/html
done
This script is not copying data which is therein path /home/ec2-user/PVs/clear-nginx-deployment of the master node.
But it works fine when I try the same script manually on the destination cluster.
I am using python's paramiko.SSHClient() for executing the script remotely:
def ssh_connect(ip, user, password, command, port):
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, username=user, password=password, port=port)
stdin, stdout, stderr = client.exec_command(command)
lines = stdout.readlines()
for line in lines:
print(line)
except Exception as error:
filename = os.path.basename(__file__)
error_handler.print_exception_message(error, filename)
return
To make sure the above function is working fine, I tried another script:
#!/usr/bin/bash
cd /home/ec2-user/PVs/clear-nginx-deployment
mkdir kk
This one runs fine with the same python function, and creates the directory 'kk' in desired path.
If you could please suggest the reason behind, or suggest an alternative to carry out this.
Thank you in advance.
The issue is now solved.
Actually, the issue was related to permissions which I got to know later. So what I did to resolve is, first scp the script to remote machine with:
scp script.sh user#ip:/path/on/remote
And then run the following command from the local machine to run the script remotely:
sshpass -p "passowrd" ssh user#ip "cd /path/on/remote ; sudo su -c './script.sh'"
And as I mentioned in question, I am using python for this.
I used the system function in os module of python to run the above commands on my local to both:
scp the script to remote:
import os
command = "scp script.sh user#ip:/path/on/remote"
os.system(command)
scp the script to remote:
import os
command = "sshpass -p \"passowrd\" ssh user#ip \"cd /path/on/remote ; sudo su -c './script.sh'\""
os.system(command)

Putty: trying to send multiple commands to remote server but only the first is executed [duplicate]

I want to run multiple commands automatically like sudo bash, ssh server01, ls , cd /tmp etc at server login..
I am using Remote command option under SSH in putty.
I tried multiple commands with delimiter && but not working.
There is a some information lacking in your question.
You say you want to run sudo bash, then ssh server01.
Will sudo prompt for a password in your remote server?
Assuming there is no password in sudo, running bash will open another shell waiting for user input. The command ssh server01 will not be run until that bash shell is exited.
If you want to run 2 commands, try first simpler ones like:
ls -l /tmp ; echo "hi there"
or if you prefer:
ls -l /tmp && echo "hi there"
Does this work?
If what you want is to run ssh after running bash, you can try :
sudo bash -c "ssh server01"
That is probably because the command is expected to be a program name followed by parameters, which will be passed directly to the program. In order to get && and other functionality that is provided by a command line interpreter such as bash, try this:
/bin/bash -c "command1 && command2"
I tried what I suggested in my previous answer.
It is possible to run 2 simple commands in putty separated by a semicolon. As in my example I tried with ls and echo. The remote server runs them and then the session closes.
I also tried to ssh to a remote server that is configured for not asking for a password. In that case, it also works, I get connected to the 2nd server and I can run commands on it. Upon exit, the 2 connections are closed.
So please, let us know what you actually need / want.
You can execute two consecutive commands in PuTTY using a regular shell syntax. E.g. using ; or &&.
But you want to execute ssh server01 in sudo bash shell, right?
These are not two consecutive commands, it's ssh server01 command executed within sudo bash.
So you have to use a sudo command-line syntax to execute the ssh server01, like
sudo bash ssh server01

Append to a remote environment variable for a command started via ssh on RO filesystem

I can run a Python script on a remote machine like this:
ssh -t <machine> python <script>
And I can also set environment variables this way:
ssh -t <machine> "PYTHONPATH=/my/special/folder python <script>"
I now want to append to the remote PYTHONPATH and tried
ssh -t <machine> 'PYTHONPATH=$PYTHONPATH:/my/special/folder python <script>'
But that doesn't work because $PYTHONPATH won't get evaluated on the remote machine.
There is a quite similar question on SuperUser and the accepted answer wants me to create an environment file which get interpreted by ssh and another question which can be solved by creating and copying a script file which gets executed instead of python.
This is both awful and requires the target file system to be writable (which is not the case for me)!
Isn't there an elegant way to either pass environment variables via ssh or provide additional module paths to Python?
How about using /bin/sh -c '/usr/bin/env PYTHONPATH=$PYTHONPATH:/.../ python ...' as the remote command?
EDIT (re comments to prove this should do what it's supposed to given correct quoting):
bash-3.2$ export FOO=bar
bash-3.2$ /usr/bin/env FOO=$FOO:quux python -c 'import os;print(os.environ["FOO"])'
bar:quux
WFM here like this:
$ ssh host 'grep ~/.bashrc -e TEST'
export TEST="foo"
$ ssh host 'python -c '\''import os; print os.environ["TEST"]'\'
foo
$ ssh host 'TEST="$TEST:bar" python -c '\''import os; print os.environ["TEST"]'\'
foo:bar
Note the:
single quotes around the entire command, to avoid expanding it locally
embedded single quotes are thus escaped in the signature '\'' pattern (another way is '"'"')
double quotes in assignment (only required if the value has whitespace, but it's good practice to not depend on that, especially if the value is outside your control)
avoiding of $VAR in command: if I typed e.g. echo "$TEST", it would be expanded by shell before replacing the variable
a convenient way around this is to make var replacement a separate command:
$ ssh host 'export TEST="$TEST:bar"; echo "$TEST"'
foo:bar

ssh can use in bash shell, can't use in shell file

I use ssh to login EC2(Amazon)
ssh -i /home/XXX/mykey.pem ec2-user#ec2-NN-NNN-NN-NN.us-foo-N.compute.amazonaws.com
It success,but when I write the command to the file like this:
login.sh
#! /bin/bash
ssh -i /home/XXX/mykey.pem ec2-user#ec2-NN-NNN-NN-NN.us-foo-N.compute.amazonaws.com
after chmod +x login.sh
I run the script, it return:
ssh: Could not resolve hostname
So how to solve it, thanks.
There are two likely reasons:
You have a typo in the hostname in the script.
The script has a CRLF instead of LF as the line ending on the ssh line. This often happens when you edit the file on a Windows system and transfer it to Unix. Use dos2unix to fix the script.

bash command doesnt seem to work, but its echo does?

Well, I'm new to linux so this may be a very newbie kinda of thing, here it goes:
I have a script in which I'm trying to send some different jobs to remote computers (in fact Amazon's EC2 instances), these jobs are in fact the same function which I run with different parameters.
eventually in the script code I have this line:
nohup ssh -fqi key.pem ubuntu#${Instance_Id[idx]} $tmp
if I do:
echo nohup ssh -fqi key.pem ubuntu#${Instance_Id[idx]} $tmp
I get:
nohup ssh -fqi key.pem ubuntu#ec2-72-44-41-228.compute-1.amazonaws.com '(nohup ./Script.sh 11 1&)'
Now the weird thing. If I run the code with no echo in the script it doesnt work! it says in the nohup.out (in my laptop, no nohup.out is created in the remote instance) bash: (nohup ./Script.sh 10 1&): No such file or directory
The file does exist locally and remotely and is chmod +x.
If I simply run the very same script with an echo in front of the problematic line and copy its output and paste in the terminal, it works!.
Any clues welcome, thanks!
Try removing the single quotes from $tmp. It looks like bash is treating (nohup ./Script.sh 10 1&) as the command with no parameters, but technically nohup is the command with the parameters ./Script.sh 10 1.
The problem is the single quotes around the nohup command in your $tmp variable. These don't get used on the shell locally, so SSH passes them verbatim. This means remotely the ssh server tries to interpret (nohup ./Script.sh 10 1&) as a command (looks for a file named that) which there clearly isn't. Make sure you remove the single quotes in $tmp.

Resources