Python subprocess on remote MS Windows host - python

I'm trying to run netsh command on remote windows hosts (windows domain environment with admin rights). The following code works fine on local host but I would like to run it on remote hosts as well using python.
import subprocess
netshcmd=subprocess.Popen('netsh advfirewall show rule name=\”all\”', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE )
output, errors = netshcmd.communicate()
The problem is that I'm no sure how/what method to use to initiate the connection to remote hosts and then run the subprocess commands. I cannot use ssh or pstools and would like try to implement it using existing pywin32 modules if possible.
I have used WMI module in a past which makes it very easy to query remote host but I couldn't find any way to query firewall policies over WMI and that's why using subprocess.

First you login the remote host machine using of pxssh modules Python: How can remote from my local pc to remoteA to remoteb to remote c using Paramiko
remote login of windows:
child = pexpect.spawn('ssh tiger#172.16.0.190 -p 8888')
child.logfile = open("/tmp/mylog", "w")
print child.before
child.expect('.*Are you sure you want to continue connecting (yes/no)?')
child.sendline("yes")
child.expect(".*assword:")
child.sendline("tiger\r")
child.expect('Press any key to continue...')
child.send('\r')
child.expect('C:\Users\.*>')
child.sendline('dir')
child.prompt('C:\Users\.*>')
Python - Pxssh - Getting an password refused error when trying to login to a remote server
and send your netsh command

I will recommend using Fabric, it's a powerful python tool with a suite of operations for executing local or remote shell commands, as well as auxiliary functionality such as prompting the running user for input, or aborting execution:
install fabric : pip install fabric
write the following script named remote_cmd.py:
"""
Usage:
python remote_cmd.py ip_address username password your_command
"""
from sys import argv
from fabric.api import run, env
def set_host_config(ip, user, password):
env.host_string = ip
env.user = user
env.password = password
def cmd(your_command):
"""
executes command remotely
"""
output = run(your_command)
return output
def main():
set_host_config(argv[1], argv[2], argv[3])
cmd(argv[4]))
if __name__ == '__main__':
main()
Usage:
python remote_cmd.py ip_address username password command

Related

How do I copy files from windows system to any other remote server from python script?

I don't want to use external modules like paramiko or fabric. Is there any python built in module through which we can transfer files from windows. I know for linux scp command is there like this is there any command for windows ?
Paramiko is stable, simple and supports Linux, OS X and Windows.
You can install via pip:
pip install paramiko
Simple Demo:
import base64
import paramiko
key = paramiko.RSAKey(data=base64.b64decode(b'AAA...'))
client = paramiko.SSHClient()
client.get_host_keys().add('ssh.example.com', 'ssh-rsa', key)
client.connect('ssh.example.com', username='strongbad', password='thecheat')
stdin, stdout, stderr = client.exec_command('ls')
for line in stdout:
print('... ' + line.strip('\n'))
client.close()
Something similar to scp is the Copy-Item cmdlet that's available in Powershell, You could execute powershell and run a Copy-Item command to copy a file from your local windows system to another directory or a remote server directory.
You need to first set the PowerShell for unrestricted access by doing Set-ExecutionPolicy Unrestriced after which you can use the subprocess module of python to make a call to execute the required script.
Maybe this answer is of help to you.
Server
python -m http.server
this will create a http server on port 8000
client
python -c "import urllib; urllib.urlretrieve('http://x.x.x.x:8000/filename', 'filename')"
where x.x.x.x is your server ip, filename is what you want to download

Connection ssh via python in a Windows System

I am a beginner in python development.
In fact , I want to make an ssh connection through a python code ,
do you have an idea?
I'd suggest using fabric module. It's rather simply to use, for example:
from fabric.api import env, run
env.host_string = 'xxx.xxx.xxx.xxx'
env.user = 'username'
env.password = 'password'
run('ls -l')
That's just a simple example, but it should get you started.

execute a program on a remote machine python

I can execute a script from python environment locally using subprocess but due to cross platform issues, I have to execute it on a remote server and get back the results on my local machine.
The directory parserpath contains some third party modules that can be executed using a script run.sh present in parserpath directory. However this parserpath directory is present on a remote server.
This is what I have, but this will work only if parserpath is a local directory. How can I ssh to a remote directory and run the script run.sh?
def run_parser(filename):
current_dir = os.getcwd()
parser_path="/parserpath"
os.chdir(parser_path)
subprocess.call("./run.sh " + filename, shell=True)
os.chdir(current_dir)
With most linux shells, you can run a command in a different working directory by executing a subshell as in
/home/usr> (cd /usr/local/bin;pwd)
/usr/local/bin
/home/usr>
You can do the same thing through ssh to the remote system. Depending on which ssh client you use, you may thin that up a bit. For instance, with paramikos exec_command, a new remote shell is created for each command so cd /path/on/remote/machine;./run.sh is sufficient.
A minimalist example for paramiko on python 2.x is
import sys
import paramiko
try:
hostname, username, password, targetpath = sys.argv[1:5]
except ValueError:
print("Failed, call with hostname username password targetpath")
command = "cd {};pwd".format(targetpath)
print("Command to send: {}".format(command))
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=hostname, username=username, password=password)
stdin, stdout, stderr = ssh.exec_command("cd {};pwd".format(targetpath))
print(stdout.read())
ssh.close()
python3 should be similar. There are other options like libssh2 bindings for python, pexpects ssh support and etc...
Use SSH keys to automate the process of logging in via SSH. Here is the following code to execute a script remotely.
ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Try, ssh user#host sh path/run.sh

Using fabric how can I supply a password for psql?

I want to be able to log in to my AWS postgres database from a remote machine. I am using the following Fabric script:
import sys
from fabric.api import env, run, abort
env.port = 123
env.use_ssh_config = True
def setuser(user):
"""Sets the ssh user for the fabric script"""
env.user = user
env.password = 'mypassword'
def setenv(server):
"""Sets the environment for the fabric script"""
env.hosts = ['staging']
def sync():
# log into AWS server
run("psql --host=staging.xxx.rds.amazonaws.com --username=x_user --port=5432 --password --dbname=x_database")
run("mypassword")
I run this Fabric script using the following command:
fab -f sync_staging.py sync --password=mypassword
This logs me into the remote machine, runs the line run("psql .... and then it prompts me for a password:
[stage] out: Password for user x_user:
Is there any way that I can supply the password (or respond to the prompt) such that it logs me in automatically?
There are 2 ways of solving this that I know of:
.pgpass password file in your home directory on remote host
PGPASSWORD env variable (set on remote host)
If you need to set an environment variable on remote host, use with shell_env(PGPASSWORD='mypassword'), Fabric docs here: fabric.context_managers.shell_env
Hope it solves your problem.

Run ssh-add with Fabric in a machine

I'm running some deployment tasks with Fabric that needs to checkout/update a Mercurial repository to the machine and then execute the appropriate copying/configuration.
Every time that I instatiate a new machine (we're currently using EC2 for our infrastructure) or when I run hg pull in the machine it'll ask for my ssh key passphrase, that's a bit annoying when we need to initialize a dozen machines at a time.
I've tried to run ssh-add in Fabric when the new EC2 instance is initialized but it seems like that ssh-agent isn't running for that shell and I get a Could not open a connection to your authentication agent. message from the output of Fabric.
How would I make ssh-add work when connected to the instance by the Fabric script?
A comment on fabric's issue tracker solved this for me. It's a modified version of the lincolnloop solution. Using this "run" instead of fabric's will pipe your commands through ssh locally, allowing your local ssh-agent to provide the keys.
from fabric.api import env, roles, local, output
from fabric.operations import _shell_escape
def run(command, shell=True, pty=True):
"""
Helper function.
Runs a command with SSH agent forwarding enabled.
Note:: Fabric (and paramiko) can't forward your SSH agent.
This helper uses your system's ssh to do so.
"""
real_command = command
if shell:
cwd = env.get('cwd', '')
if cwd:
cwd = 'cd %s && ' % _shell_escape(cwd)
real_command = '%s "%s"' % (env.shell,
_shell_escape(cwd + real_command))
if output.debug:
print("[%s] run: %s" % (env.host_string, real_command))
elif output.running:
print("[%s] run: %s" % (env.host_string, command))
local("ssh -A %s '%s'" % (env.host_string, real_command))
Please note that I'm running Fabric 1.3.2, and this fix won't be needed much longer.

Categories