Shell script change shell in between - python

I've a shell script with two shebangs, the first one tells #!/bin/sh and after a few lines the other one is #!/usr/bin/env python.
When this script is given executable permission and ran as ./script.sh, the script works fine, uses /bin/sh in first part and uses python interpreter in latter part.
But when the script is run as sh script.sh, the second shebang is not recognized and the script fails. Is there anyway I can force to change the interpreter if the script is run explicitly as sh script.sh.
The reason I need this is because I need to run the scripts through a tool which runs as sh script.sh

As far as I know you cannot have two shebang lines in one script. The shebang works only when -
it is on the first line
it starts in column one
If you need to run python code then have it in another script and then call the script by doing
python path/to/the/script.py

A better way to do this would be to use a shell here document. Something like this:
#!/bin/sh
curdir=`pwd`
/usr/bin/env python <<EOF
import os
print os.listdir("$curdir")
EOF
This way, you won't need to distribute the code on two separate files.
As you see, you can even access shell variables from the python code.

have your script.sh script invoke the python interpreter directly:
#!/bin/sh
# include full path if needed
python (your python interpreter arguments)

Related

Can I run a shell command from python script in the current shell

I have a python script which invokes two different shell scripts. The first script sets some environment variables which are required by the second script. The python code has the following structure :
import subprocess
subprocess.call(["bash", "a.sh"]) #a.sh sets env_var1
subprocess.call(["bash", "b.sh"]) #b.sh reads env_var1
Because the scripts a.sh and b.sh run in different shells, the above code does not do the needful.
I want to know that can we execute these shell scripts from python in the current shell itself
You can use this line to run commands to your shell in python os.system('command to run here')
In your case it would be something like:
import os
os.system('./a.sh')
os.system('./b.sh')

Calling script-level Python functions from the Linux command line

How can I create functions and software for my Linux server? Let me explain this in a bit more detail.
So for my Linux server which I access with my SSH client, I have made a few Python scripts that work fine, but what I really want to do is have these Python scripts active all the time, such that I can execute functions I've created in the script (such as "def time(): ...") just by typing "time" in to the command line rather than starting up a script with ./script-name.py and then type "time". Do I need to install my Python files in to the system in some way?
I struggled searching Google because I didn't fully understand what to search, and results that came up weren't really related to my request. I did find the cmd Python module and learned how to create cmd interpreters, however, in order for me to access the commands I defined in the cmd interpreter, I had to first start the script, which as I explained above, not what I am looking for.
How can I make script-level Python functions callable from the Linux command line?
If you're using Python, you'll still need to fire up the interpreter, but you can make that happen automatically.
Start by making your script executable. Run this command in the shell:
chmod +x script-name.py
ls -l script-name.py
The output of ls should look something like this (note the xs in the left-hand column):
-rwxr-xr-x 1 me me 4 Jan 14 11:02 script-name.py
Now add an interpreter directive line at the top of your script file - this tells the shell to run Python to interpret your script:
#!/usr/bin/python
Then add code at the end of the file that calls your function:
if __name__ == '__main__':
time()
The if statement checks to see if this is the file that is being executed. It means you can still import your module from another Python file without the time() function being automatically called, if you want.
Finally, you need to put your script in the executable path.
mkdir -p $HOME/bin
mv script-name.py $HOME/bin/
export PATH=$HOME/bin:$PATH
Now you should be able to run script-name.py, and you'll see the output of the time() function. You can rename your file to whatever you like; you can even remove the .py extension.
Additional things you can do:
Use the argparse module to add command line arguments, e.g. so you can run script-name.py time to execute the time() function
Put the script in a system-wide path, like /usr/local/bin, or
Add the export PATH=$HOME/bin:$PATH line to your .bashrc so that it happens by default when you log in
The answer above is by far more complete and more informative than mine. I just wanted to offer a quick and dirty alternative.
echo "alias time='<your script> time'" > ~/.bashrc
bash
Like I said, quick and dirty.

Running several programs from one program

I have 12 programs which i intend to run simultaneously. Is there any way i run all of them via one single program which when built runs the 12 programs?
I am using sublime and the programs are python.
If you just want to execute the programs one by one in a batch, you can do it in a bash script. Assuming they are executables in the same folder, you can have an .sh file with the following contents:
#!/bin/bash
python ./my_app1.py &
python ./my_app2.py &
python ./my_app3.py
If the scripts themselves have the #!/usr/bin/env python at the top to identify the interpreter, you can do chmod +x on them, and turn your runner.sh file into:
#!/bin/bash
./my_app1.py &
./my_app2.py &
./my_app3.py
On the other hand, if you want to do this from a python script, you can use:
import subprocess
import os
scripts_to_run = ['my_app1.py', 'my_app2.py', 'my_app3.py']
for s in scripts_to_run:
subprocess.Popen([os.path.join(os.getcwd(), s)])
Note 1: don't forget to include the #!/usr/bin/env python in every script on the first line.
Note 2: it is important to use subprocess.Popen() instead subprocess.call() because the latter is a blocking function that will wait for the application to finish before proceeding. With subproces.Popen() you get the concurrent execution.

Use of shebang in shell scripts

In Linux, we usually add a shebang in a script to invoke the respective interpreter. I tried the following example.
I wrote a shell script without a shebang and with executable permission. I was able to execute it using ./. But if I write a similar python program, without shebang, I am not able to execute it.
Why is this so? As far as my understanding, shebang is required to find the interpreter. So how does shell scripts work, but not a python script?
My assumption is that a script without a shebang is executed in the current environment, which at the command line is your default shell, e.g. /bin/bash.
shell scripts will only work if you are in the shell you targeted ... there is not python shell ... as such python will never work without explicity calling python (via shebang or command line)
By default the shell will try to execute the script. The #! notation came later
Thereā€™a subtle distinction here. If the target is a binary or begins with a #! shebang line, then the shell calls execv successfully. If the target is a text file without a shebang, then the call to execv will fail, and the shell is free to try launching it under /bin/sh or something else.
http://en.wikipedia.org/wiki/Shebang_(Unix)
Under Unix-like operating systems, when a script with a shebang is run as a program, the program loader parses the rest of the script's initial line as an interpreter directive; the specified interpreter program is run instead, passing to it as an argument the path that was initially used when attempting to run the script.
Now when the #! is not found, every line is interpreted as native shell command. And hence if you write a bash script and run it under bash shell it will work. If you run the same bash script in say a tcsh shell it will not work without the initial #!/usr/bin/tcsh

When invoking a Python script, what is the difference between "./script.py" and "python script.py"

One difference is that "./script.py" only works if script.py is executable (as in file permissions), but "python script.py" works regardless. However, I strongly suspect there are more differences, and I want to know what they are.
I have a Django website, and "python manage.py syncdb" works just fine, but "./manage.py syncdb" creates a broken database for some reason that remains a mystery to me. Maybe it has to do with the fact that syncdb prompts for a superuser name and password from the command line, and maybe using "./manage.py syncdb" changes the way it interacts with the command line, thus mangling the password. Maybe? I am just baffled by this bug. "python manage.py syncdb" totally fixes it, so this is just curiosity.
Thanks.
Edit: Right, right, I forgot about the necessity of the shebang line #!/usr/bin/python. But I just checked, "python manage.py syncdb" and "./manage.py syncdb" are using the same Python interpreter (2.7.2, the only one installed, on Linux Mint 12). Yet the former works and the latter does not.
Could the environment variables seen by the Python code be different? My code does require $LD_LOADER_PATH and $PYTHON_PATH to be set special for each shell.
Calling ./script.py uses the "shebang line" in the script to determine which interpreter to use to run the script. Such a line might look like
#!/usr/bin/env python
or
#!/usr/bin/python2.7
or whatever path to the python interpreter is used. If it resolves to the same Python interpreter that is called by just
python
from the shell command line, there is no difference between ./script.py and python script.py, but the two version can end up using different Python interpreters.
./script.py = "Attempt to execute a file called script.py in the current shell"
python script.py = "Send script.py as an argument to the first python executable in the current $PATH"
The first only works if the file has the execute bit set for the user attempting to execute the file and it has the so-called shebang line, which tells the shell how to run it.
In Linux using terminal you can execute any file -if the user has execute permission- by typing
./fileName. When the OS sees a valid header like #! /usr/bin/python (or for perl #! /usr/bin/python), It will call the python or perl (appropriate) interpreter to execute the program. You can use the command python script.py directly because, python is a executable program located at /usr/bin (or somewhere else) which is in a environmental variable $PATH,
that corresponding to directory of executables.
./script.py runs the interpreter defined in the #! at the beginning of the file. For example, the first line might be #! /usr/bin/env python or #! /usr/bin/python or something else like that. If you look at what interpreter is invoked, you might be able to fix that problem.

Categories

Resources