psexec commands works perfectly from powershell but not recognized by python - python

disclaimer - I know there is a package pypsexec for this i'm asking why this happens and how to solve it.
the command
psexec -s -i -d \\<PC-NAME> -u <UserName> -p <Password> <Command>
works perfectly when typed manually at powershell
however when I tried mimicking this with python as
from subprocess import Popen,PIPE
p = Popen("""psexec -s -i -d \\<PC-NAME> -u <UserName> -p <Password>
<Command>""", stdin=PIPE, stdout=PIPE, shell= True )
stdout, stderr = p.communicate()
print(stdout, stderr)
I get the following:
'psexec' is not recognized as an internal or external command,
operable program or batch file.
b'' None
any idea why? psexec is configured at variable path and as i said works from cmd/powershell same error for pskill etc.
Solved - read the comments

Move psexec.exe to C:\windows\SysWOW64. 32-bit python reads from there
If you are interested, I made a package for PsExec:
You can perform a lot of fun operations with it.
Project here
Please check it out :)

Related

How to use a "sudo" with password command in a python script?

I need to run a sudo command in my script to turn on and off network connections for an script I'm doing.
The password is plain text in the code for this example, but it will be in a jumbled for in a hidden file for the real program.
I tried multiple online examples of code, including popen and call,and nothing worked, but they didnt work and I dont really understand how they work.
def run_script(script, stdin=None):
proc = subprocess.Popen(['sudo' , 'bash', '-c', script],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
proc.communicate(b'password')
command = "ip link set enp6s0 down"
run_script(command)
The script runs, but it wont actually do anything. No error.
sudo has a parameter called '-S', below helps:
sudo bash -c 'your script' -S your_password

Paramiko exec_command hangs on docker exec

I am using Paramiko to test docker commands from an external system (I need to do this I can't just build the container and test it locally) and the test case that I am trying to run involves starting up Apache Spark and running one of the examples, specifically SparkPi. For some reason my python script hangs on the docker exec ... command below. However, previously perform other docker execs and have not had a problem running everything manually. It only breaks when I put everything in the script.
Command:
stdin, stdout, stderr = ssh_client.exec_command(f'docker exec {spark_container_id} bash -c \'"$SPARK_HOME"/bin/spark-submit --class org.apache.spark.examples.SparkPi \
--master spark://$(hostname):7077 "$SPARK_HOME"/examples/jars/spark-examples_2.11-2.1.1.jar {self.slices_to_calculate}\'')
print("\nstdout is:\n" + stdout.read() + "\nstderr is:\n" + stderr.read())
Any idea what could be causing this? And why?
Found out that the reason for this is because I didn't have the get_pty=True parameter for exec_command. It must be the case that by attaching a terminal to the spark-submit command the output gets printed properly. So the solution to this would be
stdin, stdout, stderr = ssh_client.exec_command(f'docker exec -t {spark_container_id} bash -c \'"$SPARK_HOME"/bin/spark-submit ...', get_pty=True)
NOTE: By using get_pty=True the stdout and stderr of the exec_command get combined.

python: subprocess.Popen, openvpn command not found

OS X 10.13.6 Python 3.6
I am trying to run the following command from a jupyter notebook:
vpn_cmd = '''
sudo openvpn
--config ~/Downloads/configs/ipvanish-US-Chicago-chi-a49.ovpn
--ca ~/Downloads/configs/ca.ipvanish.com.crt'''
proc = Popen(vpn_cmd.split(), stdout=PIPE, stderr=STDOUT)
stdout, stderr = proc.communicate()
print(stdout.decode())
But get the error:
sudo: openvpn: command not found
What I've tried:
added export PATH="/usr/local/sbin:$PATH" to my ~/.bash_profile and can run the the sudo openvpn command from my terminal
edited my sudoers file so sudo no longer prompts for a password
called sudo which openvpn and tried adding /usr/local/sbin/openvpn to my sys.path within python
not splitting vpn_cmd and setting shell=True
tried packaging it in a test.py script and executing from the terminal, but it just hangs at the proc.communicate() line
specified the full path for the --config and --ca flags
So far, nothing has fixed this. I can run openvpn from my terminal just fine. It seems like a simple path issue but I can't figure out what I need to add to my python path. Is there something particular with the jupyter notebook kernel?
Jupyter probably isn't picking up your personal .bashrc settings, depending also on how you are running it. Just hardcode the path or augment the PATH in your Python script instead.
With shell=False you don't get the tildes expanded; so you should change those to os.environ["HOME"], or make sure you know in which directory you run this, and use relative paths.
You should not be using Popen() if run can do what you require.
home = os.environ["HOME"]
r = subprocess.run(
['sudo', '/usr/local/sbin/openvpn',
'--config', home + '/Downloads/configs/ipvanish-US-Chicago-chi-a49.ovpn',
'--ca', home + '/Downloads/configs/ca.ipvanish.com.crt'],
stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(r.stdout)

Run sequential commands in Python with subprocess

hope you can help. I need, in my Python script, to run the software container Docker with a specific image (Fenics in my case) and then to pass him a command to execute a script.
I've tried with subprocess:
cmd1 = 'docker exec -ti -u fenics name_of_my_container /bin/bash -l'
cmd2 = 'python2 shared/script_to_be_executed.py'
process = subprocess.Popen(shlex.split(cmd1),
stdout=subprocess.PIPE,stdin=subprocess.PIPE, stderr =
subprocess.PIPE)
process.stdin.write(cmd2)
print(first_process.stdout.read())
But it doesn't do anything. Suggestions?
Drop the -it flags in your call do docker, you don't want them. Also, don't try to send the command to execute into the container via stdin, but just pass the command to run in your call do docker exec.
I don't have a container running, so I'll use docker run instead, but the code below should give you a clue:
import subprocess
cmd = 'docker run python:3.6.4-jessie python -c print("hello")'.split()
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out, err = p.communicate()
print(out)
This will run python -c print("hello") in the container and capture the output, so the Python (3.6) script will itself print
b'hello\n'
It will also work in Python 2.7, I don't know which version you're using on the host machine :)
Regarding communicating with a subprocess, see the official docs subprocess.Popen.communicate. Since Python 3.5 there's also subprocess.run, which makes your life even easier.
HTH!
You can use subprocess to call Fenics as an application, section 4.4 here.
docker run --rm -v $(pwd):/home/fenics/shared -w /home/fenics/shared quay.io/fenicsproject/stable "python3 my-code.py"

running a command as a super user from a python script

So I'm trying to get a process to be run as a super user from within a python script using subprocess. In the ipython shell something like
proc = subprocess.Popen('sudo apach2ctl restart',
shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
works fine, but as soon as I stick it into a script I start getting: sudo: apach2ctl: command not found.
I would guess this is due to the way sudo handles environments on ubuntu. (I've also tried sudo -E apche2ctl restart and sudo env path=$PATH apache2ctl restart with no avail)
So my question is basically, if I want to run apache2ctl restart as super user that prompts the user for the super user password when required, how should I go about doing this? I have no intention of storing passwords in the script.
Edit:
I've tried passing in the commands as both a string and tokenized into a list. In the python interpreter, with a string I'll get the password prompt properly (still doesnt work in a python script as in my original problem), a list just gives the help screen for sudo.
Edit 2:
So what I gather is that while Popen will work with some commands just as strings when shell=True, it takes
proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])
without 'shell=True' to get sudo to work.
Thanks!
Try:
subprocess.call(['sudo', 'apach2ctl', 'restart'])
The subprocess needs to access the real stdin/out/err for it to be able to prompt you, and read in your password. If you set them up as pipes, you need to feed the password into that pipe yourself.
If you don't define them, then it grabs sys.stdout, etc...
Try giving the full path to apache2ctl.
Another way is to make your user a password-less sudo user.
Type the following on command line:
sudo visudo
Then add the following and replace the <username> with yours:
<username> ALL=(ALL) NOPASSWD: ALL
This will allow the user to execute sudo command without having to ask for password (including application launched by the said user. This might be a security risk though
I used this for python 3.5. I did it using subprocess module.Using the password like this is very insecure.
The subprocess module takes command as a list of strings so either create a list beforehand using split() or pass the whole list later. Read the documentation for more information.
What we are doing here is echoing the password and then using pipe we pass it on to the sudo through '-S' argument.
#!/usr/bin/env python
import subprocess
sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()
cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
output = cmd2.stdout.read().decode()
The safest way to do this is to prompt for the password beforehand and then pipe it into the command. Prompting for the password will avoid having the password saved anywhere in your code and it also won't show up in your bash history. Here's an example:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
# sudo requires the flag '-S' in order to take input from stdin
proc = Popen("sudo -S apach2ctl restart".split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())
You have to use Popen like this:
cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
It expects a list.
To run a command as root, and pass it the password at the command prompt, you could do it as so:
import subprocess
from getpass import getpass
ls = "sudo -S ls -al".split()
cmd = subprocess.run(
ls, stdout=subprocess.PIPE, input=getpass("password: "), encoding="ascii",
)
print(cmd.stdout)
For your example, probably something like this:
import subprocess
from getpass import getpass
restart_apache = "sudo /usr/sbin/apache2ctl restart".split()
proc = subprocess.run(
restart_apache,
stdout=subprocess.PIPE,
input=getpass("password: "),
encoding="ascii",
)
I tried all the solutions, but did not work. Wanted to run long running tasks with Celery but for these I needed to run sudo chown command with subprocess.call().
This is what worked for me:
To add safe environment variables, in command line, type:
export MY_SUDO_PASS="user_password_here"
To test if it's working type:
echo $MY_SUDO_PASS
> user_password_here
To run it at system startup add it to the end of this file:
nano ~/.bashrc
#.bashrc
...
existing_content:
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
...
export MY_SUDO_PASS="user_password_here"
You can add all your environment variables passwords, usernames, host, etc here later.
If your variables are ready you can run:
To update:
echo $MY_SUDO_PASS | sudo -S apt-get update
Or to install Midnight Commander
echo $MY_SUDO_PASS | sudo -S apt-get install mc
To start Midnight Commander with sudo
echo $MY_SUDO_PASS | sudo -S mc
Or from python shell (or Django/Celery), to change directory ownership recursively:
python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)
Hope it helps.
You can use this way and even catch errors, even can add variables to your commands. -
val = 'xy
response = Popen(f"(sudo {val})", stderr=PIPE, stdout=PIPE, shell=True)
output, errors = response.communicate()
Hope this helps.

Categories