I got a python script from which I use ssh to open a connection to a different host. During this session I’m trying to run another python script, with several arguments (the script is on my machine and not on the server) but the arguments are messing it up. It links the arguments to the python interpreter rather than my script.
My code looks like this:
ssh remotehost python2 < /path/to/script —-arg1 hello —-arg2 goodbye
And the error I’m getting is unknown option per each character in the argument’s name, for example:
Unknown option: —-
Unknown option:a
Unknown option:r
etc.. anyway I can pass arguments without getting this error? I tried using sys args but my arguments are sentences sometimes and it doesn’t parse it well..
To execute Scripts on a different server use paramiko to connect and to execute commands:
Import paramiko
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host,port,user,password)
stdin, stdout, stderr = client.exec_command('python2 /path/to/script hello goodbye')
client.close()
Full doc:
http://docs.paramiko.org/en/stable/api/client.html
to run a local script on a different server use:
ssh user#machine python < script.py - arg1 arg2
see Run local python script on remote server
Related
I have a shell script stored on my local machine. The script needs arguments as below:
#!/bin/bash
echo $1
echo $2
I need to run this script on a remote machine (without copying the script on the remote machine). I am using Python's Paramiko module to run the script and can invoke on the remote server without any issue.
The problem is I am not able to pass the two arguments to the remote server. Here is the snippet from my python code to execute the local script on the remote server:
with open("test.sh", "r") as f:
mymodule = f.read()
c = paramiko.SSHClient()
k = paramiko.RSAKey.from_private_key(private_key_str)
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect( hostname = "hostname", username = "user", pkey = k )
stdin, stdout, stderr = c.exec_command("/bin/bash - <<EOF\n{s}\nEOF".format(s=mymodule))
With bash I can simply use the below command:
ssh -i key user#IP bash -s < test.sh "$var1" "$var2"
Can someone help me with how to pass the two arguments to the remote server using Python?
Do the same, what you are doing in the bash:
command = "/bin/bash -s {v1} {v2}".format(v1=var1, v2=var2)
stdin, stdout, stderr = c.exec_command(command)
stdin.write(mymodule)
stdin.close()
If you prefer the heredoc syntax, you need to use the single quotes, if you want the argument to be expanded:
command = "/bin/bash -s {v1} {v2} <<'EOF'\n{s}\nEOF".format(v1=var1,v2=var1,s=mymodule)
stdin, stdout, stderr = c.exec_command(command)
The same way as you would have to use the quotes in the bash:
ssh -i key user#IP bash -s "$var1" "$var2" <<'EOF'
echo $1
echo $2
EOF
Though as you have the script in a variable in your Python code, why don't you just modify the script itself? That would be way more straightforward, imo.
Obligatory warning: Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".
I have the script below (test.py on 1.1.1.1) to run another remote script on another server (script.py on 2.2.2.2). I have set up the ssh keys so I don't get prompted for password.
import subprocess
USER="user"
SERVER_IP="2.2.2.2"
SCRIPT_PATH="/home/abc/script.py"
print ("ssh {0}#{1} '/usr/bin/python {2} aaa bbb'".format(USER, SERVER_IP, SCRIPT_PATH))
rc = subprocess.check_output("ssh {0}#{1} '/usr/bin/python {2} aaa bbb'".format(USER, SERVER_IP, SCRIPT_PATH))
script.py itself is on 1.2.3.4, and takes in 2 arguments.
If I copy the command that is printed out in the script, I can execute script.py successfully on 1.1.1.1. But running test.py on 1.1.1.1 gives me an error:
OSError: [Errno 2] No such file or directory
I don't understand why the script didn't work but the exact same command works on its own.
Use the additional argument:
shell=True
Your command will be:
rc = subprocess.check_output("ssh {0}#{1} '/usr/bin/python {2} aaa bbb'".format(USER, SERVER_IP, SCRIPT_PATH),shell=True)
I assume you need a shell to run a python script.
If your question is to address the need of executing a remote command and not making your script working - then if I could introduce Paramiko:
import paramiko
ssh_handle = paramiko.SSHClient()
ssh_handle.load_system_host_keys()
ssh_handle.connect(
hostname=address,
port=int(port),
username=login)
stdin, stdout, stderr = ssh_handle.exec_command("whoami")
IMO it's currently the most "usable" SSH library and works just fine in my projects.
I am executing a script that resides on the remote server.
This bash script makes use of a variable.
This variable is defined in ~/.profile.
For this purpose lets say it
$MYVAR=/a/b/c
So on remote server, or even ssh to remote and I execute
echo $MYVAR returns /a/b/c as you would expect.
But if I execute the remote script locally using python subprocess, the script fails. It fails as the script uses the $MYVAR which translates as soemthing incorrect.
This is because I am executing it via SSH, the ~./profile must not be getting loaded and instead it is using some other profile.
see here https://superuser.com/questions/207200/how-can-i-set-environment-variables-for-a-remote-rsync-process/207262#207262
Here is the command executed from a python script
ssh = subprocess.Popen(['ssh', '%s' % env.host, 'cd /script/dir | ./myscript arg1 arg2'],shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
My question is how can I run a script locally, that will ssh to remote, load the users ~/.profile then execute a bash script.
you can use paramiko module to run the scripts on remote server from locally.
http://www.paramiko.org/
Once installed , you can run the command as shown in example below
import paramiko
command=" 'ssh', '%s' % env.host, 'cd /script/dir | ./myscript arg1 arg2' "
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.18.1.26',port=22,username='root',password='defassult') #This will connect to remote server
stdin,stdout,stderr=ssh.exec_command(command) #This will execute the command on remote server
output=stdout.readlines()
print '\n'.join(output)
The easiest solution for this was to create a sort of wrapper script like so
#!/bin/bash
. /users/me/.profile
cd /dir/where/script/exists/
exec script LIVE "$#"
So now then create a method in the python script to scp the wrapper script to tmp dir
scp wrapper user#remote:/tmp
Now ssh command in the question becomes
subprocess.Popen(['ssh', '%s' % env.host, env.installPatch],shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
env.installPatch translates to:
cd /tmp; ./wrapper 'patch_name'
Now the .profile is loaded and the patch script has the correct variable vals.
With using exec I get all the output back from the patch o/p and can write to file.
This was the cleanest solution for my case.
I am trying to ssh a server using Paramiko and execute a command. But the paramiko.exec_command() returns with an error.Why is this happening?
This is my Python script:
import paramiko
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.126.141.132', username='usrm', password='passwd')
stdin, stdout, stderr = ssh.exec_command("show chassis")
print(stdout.readlines())
ssh.close()
When executed it returns with this message:
['Extra params found in CLI, this is not supported, exiting the CLI session:\n']
I am using Python 3.5.2 :: Anaconda 4.1.1 (64-bit) with Paramiko on Windows.
I have tried the commands manually and it is working.
Based on your latest comment:
I installed a Cygwin Terminal and SSH'd the server with the command...it came up with the Extra params error. Command I executed: ssh usrm#10.126.141.132 "show chassis", Output: No entry for terminal type "dumb"; using dumb terminal settings. Extra params found in CLI, this is not supported, exiting the CLI session:
it sounds like the usrm account's login shell on the SSH server is not allowed to run commands in the non-interactive way. To solve the problem you have to use invoke_shell() like this:
chan = ssh.invoke_shell()
chan.sendall('show chassis\r')
s = chan.recv(4096)
print s
I am trying to write python script that will pass the following command to be executed in a particular server.
ssh server 'mongo /path/to/file --eval "print('123456\t78');"'
The command above is passed to the following function in my script:
def runCommand(command):
process = subprocess.Popen(command,stdout=subprocess.PIPE,shell=True)
(out,err) = process.communicate()
return out
It turns out, I get the following output:
the command: ssh server 'mongo /path/to/file.js --eval "print('123456\t78');"'
MongoDB shell version: 2.6.11
connecting to: test
2016-01-26T09:42:51.084+0000 SyntaxError: Unexpected token ILLEGAL
However, when I tried to execute 'mongo /path/to/file.js --eval "print('123456\t78');"' directly on the server, it works fine as I get the result:
MongoDB shell version: 2.6.11
connecting to: test
123456 78
test
1
0
I suspect, it must has something to do with the (single) quote after ssh server. So my question are, how does the best way to pass command with special characters, like quotes or slash, to be run with the ssh command?