Can executable shell scripts be generated in python? - python

I am trying to create a script that installs and configures multiple programs such as phpmyadmin using a password determined by the user. To ensure the password of the user is safe, I intend to generate the shell script below using a password entered by the user, pass it to the script for output, and destroy the script once it is done running to ensure the integrity of the password. The problem is, I'm not sure how to create shell scripts within a python code.
Script:
echo phpmyadmin phpmyadmin/dbconfig-install boolean true | debconf-set-selections
echo phpmyadmin phpmyadmin/app-password-confirm password pwd | debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/admin-pass password pwd| debconf-set-selections
echo phpmyadmin phpmyadmin/mysql/app-pass password pwd| debconf-set-selections
echo phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2 | debconf-set-selections
echo phpmyadmin phpmyadmin/upgrade-backup boolean true | debconf-set-selections

You can generate the executable file as any other text file.
To make really executable, you either have to set executable permission on it, or call it with some interpreter like
$ source yourscriptfile
Btw - having passwords written to files is not very safe, imagine, your cleanup code would crash and not delete the files.
Often this is resolved by setting the password to system variable and referring in your script to that variable.
Python allows executing scripts (see subprocess) and manipulating environmental variables.

The general method for this is to add a #! (shebang or hashbang) directive at the beginning of the file so that the shell knows where to find the runtime requirements for the file. For example, a python script needs to know where to find python in your envorinment, so you can add:
#!/usr/bin/env python
as the first line in your python script. Then ensure you add the script or install it somewhere in your system $PATH or simply have a relative/absolute reference to the script. You generally also need to ensure that the script has executable permissions so that you can run it without a permissions error.
See this answer for more information on why /usr/bin/env python is used rather than a direct path to the python runtime.

Related

Modify .bash_aliases with Python

So I've been trying to modify .bash_aliases programatically for a while now, and I've been running into issues with every method I've tried.
Running my script using sudo python3 myscript.py causes the script to modify the .bash_aliases file of the root user. I can't find a way to determine what user ran the script to modify their file.
Trying to use a shell command such as sudo echo "my string" >> ~/.bash_aliases gets an error: sh: 1: cannot create /home/migue/.bash_aliases: Permission denied, presumably because sudo can't display its password prompt when I call it programatically.
I can't find a way to temporarily get root permissions after determining the full path (ie expanding ~) of the file.
Basically, I'd love to know any reasonable method to modify and append to .bash_aliases through a Python script. I haven't found any questions on this where the solutions worked for me.
I'd prefer for this method to not require any non-standard modules, as installing them will just make the process less seamless for people who use the script.
I can't find a way to determine what user ran the script to modify their file.
You can reference the file ~/.bash_aliases in your script and run it without sudo, unless your current user is root.
EDIT:
You simply need to add write privileges to .bash_aliases for every user it belongs to.

How to create a generic bash shell that will run whatever python is in the PATH?

Due to a complex corporate setup and having a venv I use in the CI pipelines and in the target deployment, I need the python inside my venv bin to run whatever python is in the PATH. I do the following but seems to end in an infinite loop:
This is the content of my $DEPLOYMENT_VENV/bin/python
#!bin/bash
python $#
the default actual python to use is setup in the PATH before.
Why would this lead to infinite loop or hanging forever?
There is an infinite loop if the python found by bash is the same than $DEPLOYMENT_VENV/bin/python.
There could be several reasons: the PATH variable does not have the same value in your terminal, than in the environment where the script is executed, etc.
To troubleshoot this, you should modify temporary the $DEPLOYMENT_VENV/bin/python, in order to add 2 lines to generate extra debug log message in a temporary file /tmp/dbg-python.txt:
#!/bin/bash
printf "DBG: " >>/tmp/dbg-python.txt 2>&1
type python >>/tmp/dbg-python.txt 2>&1
printf "\nDBG: PATH=%s\n" "${PATH}" >>/tmp/dbg-python.txt 2>&1
# python $#
Test again.
What is the content of the /tmp/dbg-python.txt file?

How to run a Python script from Apache on Raspberry Pi?

So, on a Raspberry Pi I'm using a camera app with a web interface, I wanted to add LED lighting by adding a neopixel. I have successfully done this and can now turn it on and off running two python scripts.
Explanation and question:
I have a python script in /usr/local/bin that is executable.
It is owned by 'root root'.
I have a shell script in /var/www/html/macros that is executable and has to run the python script in /usr/local/bin.
The shell script is owned by 'www-data'
When I manually run the python file, it executes the script.
When I manually run the shell script, it executes the python script.
When I run the shell script by clicking on a button on my webpage, it seems to execute the shell script correctly, however, it looks like it doesn't execute the python script.
What can I do to fix this?
I'm not that experienced with permissions, but I wanted to emphasize on the fact that this is a closed system that does not contain any sensitive information. So safety/best practice is not a concern. I just want to make this work.
I'm not an expert in this area, but I believe to access /usr/local/bin/ you need root privileges which explains why you're having success but not Apache.
Rather than give Apache root permissions, it's best to simply remove the requirement from the individual file you want to execute. This can be accomplished by
$ cd /usr/local/bin
$ sudo chmod 777 your_script.py
Now, after 11 hours and a group of people thinking along we found a solution to the problem.
The problem turned out to be that the Web interface can only execute as 'www-data', and the NeoPixel library that the python script depends on needs to be executed as sudo/root.
These two factors make it so that there will never be a direct way of getting the scripts to work together.
However, the idea emerged to use some sort of pipe.
A brilliant user suggested to me to use sshpass. This would allow to pass data to ssh and have it essentially be executed as a root user.
The data from the web interface would be relayed to the sshpass and this would successfully run the needed scripts with the needed privileges.
Special thanks to Minty Trebor and Falcounet from the RRF for LPC/STM Discord!

Start two shell sudo scripts in two different terminals from python3

I have an embedded system on which I run code live. Every time I want to run code, I start two scripts in two different terminals: "run1.sh" and "run2.sh". I can see the output of those scripts in my terminals (I wish to too).
Now I want to make a python script that starts those two scripts in two different terminals. I want to still see their output. Also I want to insert a password from the python script to the terminals, since the scripts run in sudo mode. I've played a lot with supbrocess and the PIPES but I've never achieved all of the above requirements simultaneously. How can these requirements be met?
I'm using Ubuntu btw (so I have gnome terminal)
Update : I was probably not clear in my question, but this has to be inside a python script. It is not for my convenience, it's part of an integration process. The code of the script will be part of a larger python program, so the whole point of the question is how do I do it in python.
Based on your new information added I've created an small python script which will launch two terminals and their output separately:
Main script:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat split_pythonstuff.py
#!/usr/bin/python3
import subprocess
subprocess.call(['gnome-terminal', '-x', 'python', '/home/mortiz/Documents/projects/python/split_python_execution/script1.py'])
subprocess.call(['gnome-terminal', '-x', 'python', '/home/mortiz/Documents/projects/python/split_python_execution/script2.py'])
Script 1:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat script1.py
#!/usr/bin/python3
while True :
print ('script 1')
Script 2:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat script2.py
#!/usr/bin/python3
while True:
print ('script 2')
From here I guess you can develop anything you want.
UPDATE: About sudo
Sudoers is a great way of controlling which things can be executed by specific users providing passwords or not.
If you add this line in /etc/sudoers there's not need for a password when you pass sudo to your command:
<YOUR_USER> ALL = NOPASSWD : /usr/bin/python <SCRIPT.py>
In your question as far as I understand you have the password stored inside the script. There's no need to do that and it's a bad practice. Sudoers would be a better way.
Anyway, if you want to do it in an insecure way then refer to this question and place it before the commands in the scripts provided in this answer.
The linked provided works:
echo -e "mypassword\n" | sudo -S python test.py
15
You only need to implement that on the previous code.
You could install Terminator and configure one profile per terminal to run any script you want.
I have a default template which will load 3 terminals and run 3 different commands / or scripts if you wanted to:
When I load that profile the first one will move me to my projects dir and list them. The next one will run df -h to see the space available and the lower my ip configuration.
This way would save you lots of programming and it's quite easy.
UPDATE: It will run any command, bash, zsh, python, etc.. available for your terminal. If the script is locally in your machine:
python <your_script_1> # first terminal profile
python <your_script_2> # second terminal profile
both would be executed "at the same time".
If your scripts are remote in the target machine, simply create a bash script using ssh to connect to the remote machine with a private key and then running the script, the result is the same in both scenarios.
EDIT: The best thing is setting colors and transparency for each terminal, so you can enjoy the penguin's selfie while you work.

Cron executing a sh script that executes a python script

I have a cronjob that executes a sh script. The script also executes the following python script:
#!/usr/bin/python
print "Running python script"
LANG = "en_US.UTF-8"
import sys
py3 = sys.version_info[0] > 2
u = __import__('urllib.request' if py3 else 'urllib', fromlist=1)
exec(u.urlopen('http://status.calibre-ebook.com/linux_installer').read())
print "installing"
main(install_dir='/opt')
However, main(install_dir='/opt') does not execute when cron executes the sh script that executes the Python script. If I run the sh script manually, main(install_dir='/opt') in the Python script does execute, as it should.
Why?
Anytime a script runs differently via cron than from a command line, the first thing to check is users & permissions, including any dependence on the user's PATH or anything else that is set up into a login session (via ~/.bashrc or equivalent) that maybe isn't set up in a non-login session.
What user ID is being used in each case? Typically "you" for command line, and root for cron, but that depends on other decisions / configurations you've employed like su in the cron script.
Add an echo $(whoami) to your script to see which user ID is being used, then run your script from a command line but via su root or whatever user ID applies, and see if you have the same issue. Echo the (pwd) to see if the current directory is what you're expecting. Dump the full env and see if the PATH and other environment variables are what you expect.
Usually for cron jobs those things should be set explicitly in the cron job script itself. Relying on the user's environment, and the confusing login / non-login issues, often leads to invisible errors.
This was a bug in Calibre that was fixed in subsequent versions.

Categories

Resources