Paramiko exec_command does not execute the command - python

What is the way to run a .bat (or Python) script on a remote Windows server 2016? SSH server is installed and works correctly.
I tried using Paramiko, but it didn't bring any result:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('ip', username='root', password='pass')
ssh_stdin, ssh_stdout, ssh_stder = ssh.exec_command('C:/Users/Administrator/Desktop/main/videos/uniq.bat')
What am I doing wrong? The script does not run. However, if you run it manually, it works well.
The batch file is:
FOR /F "tokens=*" %%G IN ('dir /b *.mp4') DO ffmpeg -i "%%G" -vf noise=alls=1:allf=t "%%~nG_1.mp4"

The SSHClient.exec_command only starts an execution of the command. If you do not wait for it to complete and immediately kill the session, the command is killed along with it.
The most trivial way to wait for command to complete is reading its output to the end:
stdin, stdout, stderr = ssh.exec_command(command)
stdout.channel.set_combine_stderr(True)
output = stdout.readlines()
If this won't fix the problem on its own, it will at least collect any error output to help you identifying the (other) problem.

Related

paramiko - invoke script.py on remote server and continue

Im using paramiko to execute python script on remote machine.
I want paramiko to execute the script on the remote machine and continue without closing the script.
this my code now:
command = "python3 script.py"
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
client.connect(ip,port,user,password)
stdin, stdout, stderr = self.client.exec_command(command)
while(True):
"do something"
So right now the python script is starting and finishing really fast (altought it suppose to run for hour) and then "do something" happend.
I want the script.py to finish on the remoth machine while "do something" happend.
"Invoke the script and forget about it"
That's what your code does. But if the command prints (lots of) output, once the output buffers fill, the script will hang and never finish.
If you are not interested in the output, an easy solution is to discard the it:
command = "python3 script.py > /dev/null 2>&1"

Paramiko ssh connection to windows host. Empty stdout of "VBoxManage.exe guestcontrol run" command

I'm writing python script executing bash script inside virtualbox VM using paramiko python library. The code snippet below:
stdin, stdout, stderr = i[2].exec_command("\"\Program Files\Oracle\VirtualBox\VBoxManage.exe\" guestcontrol \"virtnet_proxy\" run --exe \"/home/username/show_ip.sh\" --username username --password password" )
exit_status = stdout.channel.recv_exit_status()
if exit_status == 0:
proxy_ip=stdout.readlines()
print ("got proxy ip from host ", i[0], proxy_ip, stderr.readlines())
Connects to windows host and
should print ip address of a VM's interface. If you run this command in cmd it works fine but using paramiko ssh client, stdout is empty. If you run similar code except you connect to linux virtualbox host (and run linux command) stdout.readlines() works fine and contains output of bash script. Stderr output:
VBoxManage.exe: warning: Error getting stdout handle: VERR_NOT_IMPLEMENTED\r\n', 'VBoxManage.exe: warning: Error getting stderr handle: VERR_NOT_IMPLEMENTED\r\n
Bash script:
ips=$(hostname --all-ip-addresses)
read -ra arr <<< "$ips"
echo"${arr[0]}"
As i said stdout is empty only if you connect to windows host and run vboxmanage command on guest machine.
Thank You in advance,
Wojtek
EDIT: I've changed ssh server on windows host from OpenSSH to FreeSSHd and the code worked !

Unable to see ifconfig output using paramiko

I am using below code to execute commands on a remote machine,
import paramiko
import os
dssh = paramiko.SSHClient()
dssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
dssh.connect('192.168.1.5', username='root', password='asdfghhh')
import os
stdin, stdout, stderr = dssh.exec_command('ls')
print stdout.read()
stdin, stdout, stderr = dssh.exec_command('ifconfig')
print stdout.read()
stdin, stdout, stderr = dssh.exec_command('ps')
print stdout.read()
dssh.close()
when I execute the program, Its able to show the ls and ps as well as other commands output.
however ifconfig o/p is not observed.
any idea how to solve this problems?
Thanks in advance...
Your server may be discriminating between interactive and non-interactive SSH sessions, running different startup scripts for the different sessions. Try running echo $PATH on the remote host through the paramiko SSH session and a regular interactive one and compare the outputs.
For a workaround you can do a which ifconfig on the remote server in an interactive session to get the absolute path and use that in your paramiko command.
stdin, stdout, stderr = dssh.exec_command('/abs/path/to/ifconfig')
NOTE
On one of my hosts the result of echo $PATH from the paramiko SSH client was /usr/bin:/bin, while in an interactive session it was /usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin, and ifconfig was indeed located in /usr/sbin, i.e. outside the path of the paramiko session.
To get the output for certain application binaries you must use the flag: get_pty=True
I'm still looking for the reason it happens for some commands, it's for me unknown yet. However the way I found to workaround this problem is shown in the example below:
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.2.0.230', username='ibmsys1', password='passw0rd', timeout=5)
stdin, stdout, stderr = ssh.exec_command('/sbin/ifconfig', timeout=3, get_pty=True)
print stdout.read()
Usually I would run:
#stdin, stdout, stderr = ssh.exec_command('/sbin/ifconfig')
in my example, I've just added 2 new flags, timeout=3 and get_pty=True
This solved my problem. The timeout flag is not related, however I always use it as good practice. The point here is the use of the get_pty=True
PS. I would recommend do not trust on the system $PATH, always input the full path for the application to be run, e.g: /usr/bin/my_binary or in your case /sbin/ifconfig
I hope this may help you to workaround the problem.
Good luck!

Execution python-paramiko

I am trying to execute some command to remote machine through python
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(SERVER_IP, username='root', password='xxxxx')
stdin, stdout, stderr = ssh.exec_command(
"tar -C /home -xzf /home/Tests.tar.gz;dos2unix /home/Tests/run.py;chmod +x /home/Tests/run.py;/home/Tests/run.py>/home/Tests/log.txt"
)
it seems the last command /home/Tests/run.py>/home/Tests/log.txt is not working the log.txt is not having the values, the same works well if I do /home/Tests/run.py>/home/Tests/log.txt on remote machine terminal.
How to resolve it ?
Thanks in advance
You are not transporting the client to session like so :
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(SERVER_IP, username='root', password='xxxxx')
#note the next line you are missing
ssh_session = ssh.get_transport().open_session()
Then (after the declaration of ssh_session) you may use ssh_session.exec_command(. . .).
Try that see if it works.
To make sure your paramiko code is working and the connection is being made, try something simple like
stdin, stdout, stderr = ssh.exec_command("hostname")
and make sure that stdin contains what you expect. Then have a go at debugging the command you're executing remotely:
$ tar -C /home -xzf /home/Tests.tar.gz
$ dos2unix /home/Tests/run.py
$ chmod +x /home/Tests/run.py
$ /home/Tests/run.py > /home/Tests/log.txt
If you run code on the remove machine through a regular ssh connection it must perform as you expect it to if you want it to also work over paramiko.

How to stop a blocking process using SSH as a subprocess

What I actually tried to do:
Using a python script to start a nc(netcat) on a remote host using SSH. This netcat should listen for incoming TCP connections. It could be possible that no one wants to connect to the remote host so the netcat process have to be killed.
My first idea was using the PID of the nc process on the remote host and execute a simple kill [PID] command. But I was not able to get the process id from the nc process on the remote host.
What I have tried so far was using paramiko and sshpass.
My paramiko code:
import os, sys, paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=user, password=password)
stdin, stdout, stderr = ssh.exec_command("nc -l -p"+port+"&")
print stdout.readlines()
Using sshpass:
sshProcess = subprocess.Popen(["sshpass", "-p", password, "ssh", user+"#"+hostaddress, "nc", "-l", "-p", str(destPort),"&"], stdout=subprocess.PIPE, stdin=None)
print sshProcess.stdout.read()
I tried the sshpass approach on the normal linux terminal and the pid of the netcat process was returned. But trying both approaches in a python script had the same result: the whole script was blocked instead of returning the PID. If I do not try to read the output -- that means deleting the stdout.readlines() or sshProcess.stdout.read() -- the scripts are not blocked but I also do not get the PID of the netcat process on the remote host.
I am working on a Linux machine and the remote host also runs Linux.
Remove "&" to execute nc synchronously with ssh -t then to kill nc just kill the subprocess (p.terminate()).
See how to stop reading the subprocess stdout on timeout.

Categories

Resources