running system commands on linux using python? - python

I'm wondering if someone can either direct me to a example or help me with my code for running commands on linux(centos). Basically, I am assuming I have a basic fresh server and want to configure it. I thought I could list the commands I need to run and it would work but I'm getting errors. The errors are related to nothing to make(when making thift).
I think this is because(I'm just assuming here) that python is just sending the code to run and then sending another and another and not waiting for each command to finish running(after the script fails, I check and the thrift package is downloaded and successfully uncompressed).
Here's the code:
#python command list to setup new server
import commands
commands_to_run = ['yum -y install pypy autocon automake libtool flex boost-devel gcc-c++ byacc svn openssl-devel make java-1.6.0-openjdk git wget', 'service mysqld start',
'wget http://www.quickprepaidcard.com/apache//thrift/0.8.0/thrift-0.8.0.tar.gz', 'tar zxvf thrift-0.8.0.tar.gz',
'cd thrift-0.8.0', './configure', 'make', 'make install' ]
for x in commands_to_run:
print commands.getstatusoutput(x)
Any suggestions on how to get this to work? If my approach is totally wrong then let me know(I know I can use a bash script but I'm trying to improve my python skills).

Since commands has been deprecated for a long time, you should really be using subprocess, specifically subprocess.check_output. Also, cd thrift-0.8.0 only affects the subprocess, and not yours. You can either call os.chdir or pass the cwd argument to subprocess functions:
import subprocess, os
commands_to_run = [['yum', '-y', 'install',
'pypy', 'python', 'MySQL-python', 'mysqld', 'mysql-server',
'autocon', 'automake', 'libtool', 'flex', 'boost-devel',
'gcc-c++', 'perl-ExtUtils-MakeMaker', 'byacc', 'svn',
'openssl-devel', 'make', 'java-1.6.0-openjdk', 'git', 'wget'],
['service', 'mysqld', 'start'],
['wget', 'http://www.quickprepaidcard.com/apache//thrift/0.8.0/thrift-0.8.0.tar.gz'],
['tar', 'zxvf', 'thrift-0.8.0.tar.gz']]
install_commands = [['./configure'], ['make'], ['make', 'install']]
for x in commands_to_run:
print subprocess.check_output(x)
os.chdir('thrift-0.8.0')
for cmd in install_commands:
print subprocess.check_output(cmd)
Since CentOS maintains ancient versions of Python, you may want to use this backport instead.
Note that if you want to print the output out anyways, you can just call the subprocess with check_call, since the subprocess inherits your stdout,stderr, and stdin by default.

Related

How to run bash commands from Python preferably with the os library?

I am trying to run the following python script named test.py. It contains multiple bash commands which I would like to execute in a Linux terminal (unix). This is the content of the file:
import os
os.system('echo install virtualenv')
os.system('sudo pip install virtualenv')
os.system('echo create virtual environment')
os.system('virtualenv my_virtualenvironment')
os.system('echo activate virtual environment')
os.system('source my_virtualenvironment/bin/activate')
I am running the Python script using the following in the terminal:
python3 test.py
The problem that I have is that the commands do not run the same way as they would on a Linux terminal. The output is the following error when trying to execute the last line of the Python script:
sh: 1: source: not found
The last command source my_virtualenvironment/bin/activate normally runs fine if I execute it directly in the terminal (without my Python script). Now, what does sh: 1: mean and why does it not work with my code? I would expect to get something starting with bash: .
Also I have found this solution, but I would like not to use lists for executing commands and maybe even to stick with the os library (if there is a simpler solution without os, I am also open for that):
https://stackoverflow.com/a/62355400/11535508
source is a bash built-in command, not an executable.
Use the full path to the python interpreter in your commands instead of venv activation, e.g. os.system('<venv>/bin/python ...').
The second option is to write your commands into a separate bash script and call it from python:
os.system('bash script.sh')

How to run sudo commands in shell/linux using python script

How to run sudo bash using python script
import subprocess
import os
sudoPassword2 = 'abcd1234'
command2 = 'sudo bash'
p2 = os.system('echo %s|sudo -S %s' % (sudoPassword2, command2))
I'm getting this error:
bash: line 1: abcd1234: command not found
when i tried to this also its giving error
import shlex
import subprocess
command1 = shlex.split('cd /home/backups')
subprocess.call(command1)
error cd no file or dir
tried also this :
import shlex
import subprocess
subprocess.call(["cd","/home","/backups"])
You can use os module
import os
os.system("sudo and the code you want to run")
in example:
import os
os.system("sudo apt-get vlc")
You are receiving this error because your command posts the password to the cli first without being asked for it. So bash will interpret it as a command which, obviously, can not be executed.
Better do os.system('sudo command') and call the script as root or via sudo. This will make sure you have the necessary privileges within the script immediately at run time.
Another reason why you definitely want to refrain from doing what you do is the necessity of having the sudo password for your machine written into the script in plain text. Never do that. It's evil.
If there is no way around you can make sudo execute a command without asking for a password by adding NOPASSWD directives to the /etc/sudoers by using the editor visudo (never use anything different) like so:
user host = (root) NOPASSWD: /sbin/shutdown
user host = (root) NOPASSWD: /sbin/reboot
But if you do make sure you know that this opens the execution of this command to anyone on the system without needing elevated rights. This can be a huge security risk.

Sending CMD command prompts using Subprocess (Python)

This is a beginner level question for anyone pro in subprocess.
In Windows, is it possible for me to send the following CMD commands using subprocesssuch that they are executed one after another in a single shell:
cd C:\Users\User\myvirtualenvs\project1
Scripts\activate.bat
Hello.py
Effectively, I am trying to load the Virtualenv without having to manually myself touch CMD prompt.
Thanks in advance :)
Just like mentioned in the Comment with &&:
from subprocess import call
call(r'cd C:\ && echo 123 && dir', shell=True)
Please notice the shell=True argument.
Edit due to comment:
Shell=True is an security issue, if you're passing raw input values to the call. See this example from the docs:
from subprocess import call
filename = input("What file would you like to display?\n")
>>> What file would you like to display?
>>> non_existent; rm -rf / #
call("cat " + filename, shell=True) # Uh-oh. This will end badly...
In initially thought you want to make a small script for personal purposes. If you want to give this code away, think about packaging your code via distutils or setuptools.

Why is my Python script writing Windows style carriage returns?

I am trying to write a script that creates a fabfile, saves it and then runs it. Here is my code so far:
#!/usr/bin/python
bakery_internalip = "10.10.15.203"
print "[....] Preparing commands to run within fabfile.py"
fabfile = open("sfab.py", "w")
fabfile.write("from fabric.api import run, sudo, task\n\n#task\ndef myinstall():\n\tsudo('yum install httpd')")
fabfile.close
print "Running Fab Commands"
import subprocess
subprocess.call(['fab', '-f', 'sfab.py', '-u ec2-user', '-i', 'id_rsa', '-H', bakery_internalip, 'myinstall'])
The contents of my fabfile are as follows:
[root#ip-10-10-20-82 bakery]# cat sfab.py
from fabric.api import run, sudo, task
#task
def myinstall():
sudo('yum install httpd')
My script gives the following error when I run it:
Fatal error: Fabfile didn't contain any commands!
However, if I run dos2unix on the file and then run the following, it works fine:
fab -f sfab.py -H localhost myinstall
Simple typo fabfile.close should be fabfile.close()
Running without closing will give you:
Running Fab Commands
Fatal error: Fabfile didn't contain any commands!
Aborting
with open("sfab.py", "w") as fabfile:
fabfile.write("from fabric.api import run, sudo, task\n\n#task\ndef myinstall():\n\tsudo('yum install httpd')")
Alway use with as above to open your files, it will automatically close them for you and avoid these simple errors.
I assume you are running it on Windows.
When using open(path, "w"), Python uses the OS's native linebreak combo.
To use \n specifically use open(path, "wb").
For more information see open().

Running sudo command via CGI (Python)

I am writing a test suite for a web application using Selenium.
In the course of which I need to test behaviour of the app in case a certain service is running or not.
I wanted to create a cgi call to a Python script turning that service on and off.
I know that the cgi call is in the context of the webserver (Apache) however thought that issuing sudo calls like so:
import subprocess
import os
command = 'sudo -S launchctl unload /Library/LaunchAgents/com.my.daemon.plist'
pwd = 'pwd123'
test1 = subprocess.Popen( command, shell=True, stdin=subprocess.PIPE)
test1.communicate(input=pwd)
test2 = os.system( 'echo %s|%s' % (pwd,command) )
would do the trick, well they don't I get return code 256.
What can I do to have this call be executed w/o touching the context in which Apache runs?
As for security: this will only run on a test machine.
The user that Apache runs as needs to be in the /etc/sudoers file, or belong to the sudo group, which I guess it usually doesn't. You also need to make it not ask for a password, which is configured in /etc/sudoers
For Ubuntu, check these out: https://askubuntu.com/questions/7477/how-can-i-add-a-new-user-as-sudoer-using-the-command-line
https://askubuntu.com/questions/147241/execute-sudo-without-password
It could potentially be a pathing issue..
Have you tried writing out the full path like this:
command = '/usr/bin/sudo -S launchctl unload /Library/LaunchAgents/com.my.daemon.plist'
command should be a list, not a string. Try with:
command = ['sudo', '-S', 'launchctl', 'unload', '/Library/LaunchAgents/com.my.daemon.plist']
Cant run sudo this way -- sudo needs a controlling terminal to run.

Categories

Resources