I know others have asked similar questions to this, but what I want to know is whether or not there is a way to simply open a cmd window (on windows 10), leave it open and have a python script automatically type into it.
What I actually need to do is SSH into a remote computer and then from that remote computer, run IDL commands. I have not found a way to do this with subprocess Popen or with Paramiko to SSH. In the case of subprocess, I can't get past authentication to get into the host, i.e. I can't figure out how to type a password in. With Paramiko I am able to get into the remote computer but once there I can't get my IDL code to run, and if it does run it just hangs on that command and won't output anything, even after closing.
It seems to me that rather than sending commands directly to cmd through a subprocess or os command, it would make it much easier if I could just send a string to an open cmd window and have it execute the command and read the result. I'm going through a remote computer and then running IDL code on that remote computer so there are two layers that python has to get through. If I could just write in the cmd terminal it would make my life much easier, rudimentary as it is.
Apologies if I don't have the right lingo with all of this, I'm definitely not a network programmer.
Below is my attempt to use Paramiko. The "ls" command works and the contents of the folder I'm in are printed so I know I've accessed the remote computer, but my idl command does not print anything. Printing the output from the "idl" command itself just causes the program to hang there.
import paramiko
host = "<hostname>"
user = "<myusername>"
password = input("pass:")
client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, username=user, password=password)
_stdin, _stdout,_stderr = client.exec_command("ls", get_pty=True)
print(_stdout.read().decode())
_stdin, _stdout,_stderr = client.exec_command("idl")
_stdin, _stdout,_stderr = client.exec_command("<my command>")
print(_stdout.read().decode())
client.close()
I made much less progress with os and/or subprocess as I can't even get into the remote computer with either of those.
Related
I've spent hours messing with this, scouring the web, and generally finding no luck. Here's the setup:
Windows 10
Python 3 (playing in REPL w/ VS Code)
SFTP server authenticating via password only
Large 1+ gigabyte file to PUT
Initially I wrote a little Pysftp (Paramiko) code:
import pysftp
with pysftp.Connection(host=host, username=username,
password=password, cnopts=sftp_options) as sftp:
sftp.put(localpath, remotepath, confirm=True)
That worked for smaller files when testing. It also succeeded running with a large file but then no file could be found when looking back at the folder. My groundless hunch is that it somehow took too long and Paramiko unwittingly shot the bits into a void.
I turned to the sftp command-line utility which conveniently works on Windows 10. I was able to manually test that uploading works like so:
sftp username#host
Welcome to this funky Secure FTP Server. Please enter your password:
sftp> PUT localpath remotepath
sftp> QUIT
The key problem was the password input, obviously, and I bent over backwards trying to automate this with Popen(). I read and ruminated over these on StackOverflow: Use subprocess to send a password and Python: How to read stdout of subprocess in a nonblocking way. None of this playing resulted in anything.
I was able to read output but input always seemed to come from my keyboard only. Then I tried Pexpect which also did not work because on Windows it operates differently and won't work on some programs:
PopenSpawn is not a direct replacement for spawn. Many programs only offer interactive behaviour if they detect that they are running in a terminal. When run by PopenSpawn, they may behave differently.
UPDATE 11/19: I was able to execute PuTTY's command-line psftp.exe which accepts password as a parameter. I also confirmed that Pysftp/Paramiko with that large file worked fine against an SFTP server I setup myself so it's something to do with the vendor's server (nothing I can do anything about). I'll continue plugging at this and hopefully have a comprehensive answer to post here.
Aside from resorting to Ubuntu via WSL, does anyone have any ideas for how to upload a file to an SFTP server using Python 3.x on Windows?
Use case
On a unix server , when login manually ,opens a command shell of its own to run the command.
I am trying to automate this by using paramiko , however , somehow i am not able to execute the command on command shell using paramiko
What i have done ?
I created a simple script which is able to make connection, but its not executing command on Vshell as the ouput is always coming empty.
import paramiko
import sys
ssh_client=paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=sys.argv[1],port=sys.argv[2],username=sys.argv[3],password=sys.argv[4])
command="show hwid"
stdin,stdout,stderr=ssh_client.exec_command(command)
out=stdout.read()
print out
err=stderr.read()
print err
ssh_client.close()
The same script runs perfectly fine , when its used on server where vshell is not being used
Anyhelp or suggestion on this?
stdin,stdout,stderr=ssh_client.exec_command(command)
Regarding this line of code, I suspect that the SSH server is not properly configured to allow commands to be executed in this way (this is the equivalent of ssh myserver show hwid, rather than typing it into the terminal after login).
You might want to imitate the behaviour of typing the command in after logging into the server, and for that I think this is appropriate:
shell = ssh_client.invoke_shell()
stdin, stdout, stderr = shell.exec_command(command)
I am trying to automate a task through a Python script. The idea is to login as a regular user and then send a su command and switch to the root account.
The reason I can't directly login as root is that SSHD doesn't allow root logins.
Here's what I have:
ip='192.168.105.8'
port=22
username='xyz'
password='abc'
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)
print ("SSH connection established")
stdin,stdout,stderr=ssh.exec_command('sudo fast.sh')
outlines=stdout.readlines()
outlines+=stderr.readlines()
resp=''.join(outlines)
print(resp)
Now, I want to send the su command and echo the root password. I am aware this is not good practice but I need a quick and easy way to test this so I am OK with that.
However, when I do this
stdin,stdout,stderr=ssh.exec_command('su') and provide the password, I get an error
su: must be run from a terminal
Can some one help me to solve this.
I am running Python script on my Windows laptop to ssh into a Linux device and then switch to the root user using the su command and echo the password so that I can run other commands as root.
Thanks.
First, as you know, automating su or sudo is not the correct solution.
The correct solution is to setup a dedicated private key with only privileges needed for your task. See also Allowing automatic command execution as root on Linux using SSH.
Anyway, your command fails because sudo is configured to require an interactive terminal with requiretty option in sudoers configuration file (as a way to deter its automation).
Paramiko (correctly) does not allocate a pseudo terminal for exec channel by default.
Either remove the requiretty option.
If you cannot remove it, you can force Paramiko to allocate pseudo terminal using get_pty parameter of exec_command method:
ssh.exec_command('sudo fast.sh', get_pty=True)
But that's not a good option, as it can bring you lot of nasty side effects. Pseudo terminal is intended for an interactive use, not for automating command execution. For some examples, see
Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?
Remove of unwanted characters when I am using JSch to run command
Removing shell stuff (like prompts) from command output in JSch
I am writing a Python CGI script that I want to run on my laptop's browser. This script will SSH into two Pis, and give the command to take a photo. The server hosting this script is on one of the Pis that I want to SSH into, and that Pi also is acting as an access point for the other Pi and my laptop to connect to (everything is a LAN, not connected to the Internet).
I am successfully able to run this script on my laptop's browser to run simple commands like ls -l on both Pis and print out the results for both on the browser. But, I ultimately want to be able to give the raspistill command to both Pis. When I do this, only the Pi with the server is taking the image, but the other Pi is not. I assume it's because permissions aren't set properly for the server (I tried running the commands as sudo but still no luck). However, if I run the same script on a Python IDLE it works fine. Can somebody help me identify the issue?
Here is my script:
#! /usr/bin/env python3
from pssh import ParallelSSHClient
import cgi
print("Content-Type: text/plain\r\n")
print("\r\n ")
host = ['172.24.1.1','172.24.1.112']
user = 'XXXX'
password = 'XXXX'
client = ParallelSSHClient(host, user, password)
output = client.run_command('raspistill -o test.jpg', sudo=True)
// AMENDMENT:
for line in output['172.24.1.1'].stdout: // works as well with '172.24.1.112'
print(line)
AMENDMENT:
Apparently, if I output anything from the stdout it works fine. Why is this the case? Is is just waiting for me flush the output or something? I suspect this might be a issue with the pssh package I am using.
In your pi, go into the terminal and type sudo raspi-config and then navigate with the keys to camera and then enable it. This will restart you pi.
From https://www.raspberrypi.org/documentation/configuration/camera.md:
Use the cursor keys to move to the camera option, and select 'enable'.
On exiting raspi-config, it will ask to reboot. The enable option
will ensure that on reboot the correct GPU firmware will be running
with the camera driver and tuning, and the GPU memory split is
sufficient to allow the camera to acquire enough memory to run
correctly.
After this, go into sudo raspi-config and enable ssh (which is another option just like pi-camera). Link for this here
After thoroughly reading through the documentation for the pssh module, my problem had to do with the exit codes and how they are handled.
The documentation about run_command states that:
function will return after connection and authentication establishment and after commands have been sent to successfully established SSH channels.
And as a result:
Because of this, exit codes will not be immediately available even for
commands that exit immediately.
Initially, I was just blindly running the run_command expecting the commands to finish, but it turns out I need to get the exit codes to truly finish the processes the commands are running. The documentations states a couple of ways to do this:
At least one of
Iterating over stdout/stderr to completion
Calling client.join(output) is necessary to cause parallel-ssh to wait for commands to finish and be able to gather exit codes.
This is why in my amendment to the code, where I was outputting from stdout, the commands seemed to work properly.
I am using Python and wxpython for gui. I am trying to connect ssh tunnel. After connecting to ssh, wants a new terminal to open and have to continue my operation in local machine. How to achieve this?
I tried subprocess, pexpect and paramiko, but all are capable to connect to ssh but not open the new teminal
Below my code is there which I tried with pexpect:
import time
import sys
import pexpect
c = pexpect.spawn("ssh -Y -L xxxx:localhost:xxxx user # host.com")
time.sleep(0.1)
c.expect("[pP]aasword")
c.sendline("xxxxxx")
time.sleep(0.2)
c.interact()
c.pexpect([user#host.com~]$)
# here after its connects to ssh then command wont be executed
c.sendline("xfce4-terminal")
On 24/04/2013
I am able to open new terminal but what happens is when the new terminal will open controls from gui doesn't go there. Any help?
Opening a new local terminal and connecting an existing process in to it is a little complicated. There are at least three approaches:
Open the terminal before you start connecting, and run all the code that tries to establish the connection from within it. This is simplest. The main drawback is that the terminal will appear even if the connection fails, which might be what you want to avoid.
Run the connection attempt with a session of tmux or screen and if you detect that it succeeded then reattach that session in to a new terminal.
Make your Python program provide a pty that the terminal can attach to - your program will need to hang around and pass input and output between the remote connection and the pty.