I'm trying to install a software(it's basically a shell script) on remote Linux machine using paramiko.
I know that the software once run will prompt for a end user license acceptance (y or n).
So I wrote the script as below,
====================
`
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect ('remoteLinuxHost', username=r'user', password='pass')
stdin, stdout, stderr = ssh.exec_command(r'/full/path/to/software')
stdin.write("y\n")
stdin.flush()
print "output ", stdout.readlines()
`
This works absolutely fine on Red hat machine, but the same code hangs forever on Suse Linux! (Just prints output and script will just keeps running)
NOTE:
1.When it hangs on Suse, I manually checked
ps -ef | grep 'software' that displayed,
root 10941 10938 1 21:10 ? 00:00:00 /bin/sh software
root 11050 11031 0 21:10 ? 00:00:00 more softwareEndUserLicense.txt
This confirmed that prompt (y or n) is not being answered here.
I've tried using ssh.invoke_shell() method with the same result, also have cross checked permission of the software, gave sudo, preceded it with /bin/bash nothing working.
Please suggest.
Thank you.
Related
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.
I think I may of been googling this stuff wrong, however I was wondering if I could have my raspberry Pi execute a command after I connect to it via SSH.
Workflow:
1) SSH into Pi via terminal
2) Once logged in, the Pi executes a command to display the current temperature (I already know of this command)
The pi already outputs
Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jul 11 15:11:35 2014
I could be misunderstanding this all together, perhaps even have the command executed and shown in the dialog above.
What you're looking for is the motd which is quite common on various linux distros. This is not in python (but can be). The motd runs multiple commands on login via SSH and constructs a message which it outputs to the user. More information on this (which actually has temperature listed) can be found here: Rapberry Pi Welcome Message. The problem is this will likely change slightly depending on linux distros. A good git repo which has a nice message can also be found here: Raspberry Pi Motd
Yup, this can been done. The method that I am aware of utilizes subprocess https://docs.python.org/2/library/subprocess.html. As long as you know the name of the python script and the arguments (if any) you can pass them into subprocess. Here is an example of how to connect via python ssh script (taken from http://python-for-system-administrators.readthedocs.org/en/latest/ssh.html):
import subprocess
import sys
HOST="www.example.org"
# Ports are handled in ~/.ssh/config since we use OpenSSH
COMMAND="uname -a"
ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = ssh.stdout.readlines()
if result == []:
error = ssh.stderr.readlines()
print >>sys.stderr, "ERROR: %s" % error
else:
print result
Just append the command to the ssh-command.
ssh user#server "echo test"
"echo test" is executed on the remote machine.
You can execute a command from bash without actually logging into the other computer by placing the command after the shh command:
$ ssh pi#pi_addr touch wat.txt
Would create the text file ~/wat.txt.
This is a little cumbersome for automation however since as password must be provided so you can set a public/private RSA-key on your computer in order to be able to login to your pi remotely without a password. Simply do the following:
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa):
Created directory '/home/a/.ssh'.
Enter passphase (empty for no passphrase):
Enter the same passphrase again:
$ssh pi#pi_addr mkdir -p .ssh
$cat .ssh/id_rsa.pub | ssh pi#pi_addr 'cat >> .ssh/authorized_keys'
Don't enter a passphrase and leave everything default when running ssh-keygen. Now you will be able to rn ssh pi#pi_addr without enter a password.
Example python file:
import subprocess
SERVER = "pi#pi_addr"
subprocess.call("ssh pi#pi_addr touch wat.txt")
I have a headless Raspberry Pi which I want to have an easy means for my child to power down. I tried the following script in the apache web server:
import os
sss = os.popen('echo password | sudo -S shutdown -hP now')
print sss.read()
But nothing happens.
Then I tried:
from subprocess import Popen, PIPE, STDOUT
p = Popen('echo password | sudo -S shutdown -hP now', shell=True, stdOUT=PIPE, stderr=STDOUT)
print p.stdout.read()
Also, nothing was output and no work appears to have been done.
How can I do a shutdown from a web page?
For security reasons Apache user cannot run sudo command.
Usually this is an almost mandatory rule to save you from attacks but for a Raspberry PI installation you may not have this problem so you can just add Apache user to sudoers (or, better, uso visudo to edit that file).
Something else? Yes you may simply add shutdown permissions to Apache user, follow this tutorial. In short you have to change /etc/sudoers with:
%groupName ALL= NOPASSWD: /sbin/shutdown
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!
My scenario is I need to login to a remote machine and then do a sudo to another account like (sudo su anotheract) and then run the other required command.
But I am able to successfully connect to remote machine using below script. But the scripts hangs in the line where I am executing the sudo command(sudo su anotheract)
Can you please help me find the fix for this code?
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
ssh.connect(hostname='XX.XXX.XX.XX',port=22, username='myname',password='XXXXX')
ssh.exec_command=("sudo su anotheract")
stdout,stdin,stderr=ssh.exec_command("java -jar /usr/share/XXX/LogR.jar")
print stdout.readlines()
One (not very safe) way to do it is to pipe the password in. The caveat is that the user that you are using to connect to the box using paramiko should have sudo rights.
For example:
supass = 'some_pass'
stdout, stdin, stderr = ssh.exec_command('echo %s | sudo -S anotheract' % supass)
Again, this is not a very safe implementation but gets the job done in a jiffy.
import pxssh
ssh = pxssh.pxssh()
ssh.login('host', 'user', 'password')
ssh.sendline("sudo su anotheract")
ssh.prompt('yourrootpassword')
And in paramiko on most linux systems you cant do sudo commands thats because sudo expect commands from tty and then it isnt raise exception, but you can try method invokeshell, but I used paramiko many years ago I dont remember what was been wrong with it. If you want send various commands on shell you could use pxssh.
It can hangen because sudo waits for password. Try to add NOPASSWD: statement to the /etc/sudoers.
user ALL = NOPASSWD: /bin/true
Also it is impossible to change user using su and then continue do to something after su is finished. When su is finished, you are back to your original shell of the original user.
So you need to run all commands with sudo:
stdout,stdin,stderr = ssh.exec_command=("sudo -u anotheract java -jar /usr/share/XXX/LogR.jar")