I have numerous test servers. These test servers get re-imaged frequently, and they have the same user account and password after being re-imaged. I want to write a python script that runs a command remotely over ssh on one of these servers, without prompting user for a password, and gathers the output of the command. In some circumstance I want to run one command, get output, analyze the output. In other situation, I want to run several commands at a time (possibly run a script file). I read many postings about running commands remotely, using third party packages (e.g. paramiko). Is there a recommended way to achieve this task without using additional packages ? The server from which my script will be run might not have the package installed.
Or should I used pexpect ?
Ideally I would like to use subprocess and capture the output (providing password as an argument). Of course, my script has to handle the case when the client is logging for first time, and prompted to add ssh key to .ssh/knownhosts file.
Thank you,
Ahmed.
If host key security is not an issue (you are on a trusted network etc), you can bypass the host checking. And if you use key-based authentication there is no need for a password prompt:
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -oPasswordAuthentication=no \
-n doctor#tardis some_cmd
This way you can just use subprocess as if you executed some_cmd locally.
Related
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
Fist of all, due to Company Policy, Paramiko, or installing anything that requires administrative access to local machine it right out; otherwise I would have just done that.
All I have to work with is python with standard libraries & putty.
I am attempting to automate some tedious work that involves logging into a network device (usually Cisco, occasionally Alcatel-Lucent, or Juniper), running some show commands, and saving the data. (I am planning on using some other scripts to pull data from this file, parse it, and do other things, but that should be irrelevant to the task of retrieving the data.) I know this can be done with telnet, however I need to do this via ssh.
My thought is to use putty's logging ability to record output from a session to a file. I would like to use Python to establish a putty session, send scripted log-in and show commands, and then close the session. Before I set out on this crusade, does anyone know of any way to do this? The closest answers I have found to this all suggest to use Paramiko, or other python ssh library; I am looking for a way to do this given the constraints I am under.
The end-result would ideal be able to be used as a function, so that I can iterate through hundreds of devices from a list of ip addresses.
Thank you for your time and consideration.
If you can't use paramiko, and Putty is all you get so the correct tool is actually not Putty - it's his little brother Plink - you can download it here
Plink is the command line tool for Putty and you can your python script to call it using os.system("plink.exe [options] username#server.com [command])
See MAN Page here
Hope it will help,
Liron
I want to write a script using python. It should connect via ssh to the server and execute few commands.
The problem is, it's required to change user during connection.
As example, it's possible in WinSCP:
http://winscp.net/eng/docs/ui_login_scp#shell (Parameter Shell: You can also make use of the option to alter session startup. For example to change the user after login (known as su))
So to connect with propper rights to my ssh server I must write following command into 'Shell' field in WinSCP:
sudo su - user
I need this very feature in paramiko.
And I can't execute sudo su - user after connection is established, cause my password isn't correct. It works only when I use this 'Shell' field.
Nevertheless, when I'm connecting to the server using PuTTY(win) or ssh(linux), I don't need to enter any options, from the start it allows me to have propper rights. Seems strange for me.
I don't know how to develop it using python/paramiko.
Help me pls.
I've got some code which needs to grab code from github periodically (on a Windows machine).
When I do pulls manually, I use GitBash, and I've got ssh keys running for the repos I check so everything is fine. However when I try to run the same actions in a python subprocess I don't have the ssh services which GitBash provides and I'm unable to authenticate to the repo.
How should I proceed from here. I can think of a couple of different options:
I could revert to using https:// fetches. This is problematic because the repos I'm fetching use 2-factor authentication and are going to be running unattended. Is there a way to access an https repo that has 2fa from a command line?
I've tried calling sh.exe with arguments that will fire off ssh-agent and then issuing my commands so that everything is running more or less the way it does in gitBash, but that doesn't seem to work:
"C:\Program Files (x86)\Git\bin\sh.exe" -c "C:/Program\ Files\ \(x86\)/Git/bin/ssh-agent.exe; C:/Program\ Files\ \(x86\)/Git/bin/ssh.exe -t git#github.com"
produces
SSH_AUTH_SOCK=/tmp/ssh-SiVYsy3660/agent.3660; export SSH_AUTH_SOCK;
SSH_AGENT_PID=8292; export SSH_AGENT_PID;
echo Agent pid 8292;
Could not create directory '/.ssh'.
The authenticity of host 'github.com (192.30.252.129)' can't be established.
RSA key fingerprint is XXXXXXXXXXX
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/.ssh/known_hosts).
Permission denied (publickey).
Could I use an ssh module in python like paramiko to establish a connection? It looks to me like that's only for ssh'ing into a remote terminal. Is there a way to make it provide an ssh connection that git.exe can use?
So, I'd be grateful if anybody has done this before or has a better alternative
The git bash set the HOME environment variable, which allows git to find the ssh keys (in %HOME%/.ssh)
You need to make sure the python process has or define HOME to the same PATH.
As explained in "Python os.environ[“HOME”] works on idle but not in a script", you need to set HOME to %USERPROFILE% (or, in python, to os.path.expanduser("~") ).
I'm tired of doing this.
ssh me#somehost.com
input my password
sudo su - someuser
input my password
cd /some/working/directory
<run some commands>
Is there anyway to automate this? Do I need a special shell? or a shell emulator? can I programmatically drive the shell up to certain point then run manual commands on it?
Bonus points of it's programmed in python for extra hacking goodness
edit: All the answers below focus on the "full automation" part of the question: Where the hard part is what I highlighted above. Here is another example to see if I can capture the essence.
ssh me#somehost.com
<get a shell because keys are setup>
sudo su - user_that_deploys_the_app
<input password, because we don't want to give passwordless sudo to developers>
cd env; source bin/activate
cd /path/where/ur/app/is/staging
<edit some files, restart the server, edit some more, check the logs, etc.>
exit the term
For the ssh/authentication piece, you can setup passwordless authentication by using keys. Then you can simply use ssh and a bash script to execute a series of commands in an automated fashion.
You could use Python here, but if you are executing a series of shell commands, it's probably a better idea to use a shell script, as that's precisely what they do.
Alternately, look into Fabric for your automation needs. It's Python-based, and your "recipes" are written in Python.
I'm not quite sure what you're asking, but what you're probably asking about is getting SSH working in password-less mode using public keys. The general idea is you generate an SSH keypair:
ssh-keygen -t rsa
which gives you id_rsa and id_rsa.pub. You append the contents of id_rsa.pub to the ~/.ssh/authorized_keys file of your target user, and SSH from that point on will not ask for credentials. In your example, this will work out to:
Only once
# On your source machine
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
# Copy this to clip board
# On somehost.com
su - someuser
# edit ~/.ssh/authorized_keys and paste what you had copied from previous step
From now on, you can now just run
ssh someuser#somehost.com "sh -c 'cd /some/dir; command.sh'"
and not be prompted for credentials.
fabric is a fine choice, as others have pointed out. there is also pexpect which might be more what you're looking for.
You can play with autoexpect. It creates expect script (script language intended to handle interaction with user). Run
autoexpect ssh me#somehost.com
followed by rest of commands. Script script.exp will be created.
Please note, that exact results of input and output will be recorded by the script. If output may differ from execution to execution, you'll need to modify a bit generated script.
As Daniel pointed out you need to have a secure way of doing ssh and sudo on the boxes. Those items are universal to dealing with linux/unix boxes. Once you've tackled that you can use fabric. It's a python based tool to do automation.
You can set stuff up in your ~/.ssh/config
For example:
Host somehost
User test
See ssh_config(5) for more info.
Next, you can generate a SSH key using ssh-keygen(1), run ssh-agent(1), and use that for authentication.
If you want to run a command on a remote machine, you can just use something like:
$ ssh somehost "sh myscript.sh ${myparameter}".
I hope this at least points you in the right direction :)
If you need sudo access, then there are obvious potential security issues though ... You can use ChrootDirectory on a per user basis inside a Match block though. See sshd_config(5) for info.
try module paramiko. This can meet your requirement.