Can apache run a python script which is NOT executable? - python

I setup Ubuntu server 18.04 LTS, LAMP, and mod_mono (which appears to be working fine alongside PHP now by the way.) Got python working too; at first it gave an HTTP "Internal Server Error" message. sudo chmod +x myfile.py fixed this error and the code python generates is displayed fine. But any time the execute permission is removed from the file (such as by uploading a new version of the file), the execute bit is stripped and it breaks again.
A work-around was implemented with incrontab, where the cgi-bin folder was monitored for changes and any new writes caused chmod +x %f to be ran on them. This worked for awhile, then stopped, and seems a hokey solution at best. Perl, PHP, even ASPX do not need to be marked executable - only python.
Is there any way Apache can "run" python without the file marked as executable?

The reason PHP works, is because the interpreter is loaded into Apache. So Apache interprets the code.
For your Python, it runs as a CGI, so the interpreter is outside of Apache.
In your Python script, you probably have a #!/usr/bin/python first line (or something similar). This tells the script to run using this interpreter. This requires executable permission on the .py file, and allows you to call myfile.py directectly.
Instead run it like this: /usr/bin/python myfile.py. This way the interpreter is the executable, and it will run myfile.py as the code.
Examples
You want to run the py file "alone":
file.py
#!/usr/bin/python
print("Hello")
Running it:
./file.py
You want to run it via the python executable, like you want via Apache:
file.py
print("Hello")
Running it:
/usr/bin/python file.py

I don't think Apache is capable of serving executed python scripts without the execute bit set on the .py file.
But here is a work-around: simply leave that file marked executable, but import a second python file. That second file does not need to be marked executable.
myfile.py (marked as executable and read-only - use this with apache):
#!/usr/bin/python3
# enable debugging
# helper to run the other, non-executable file
# do not add .py to the import "filename"
import myfile2
myfile2.py (marked RW only, edit this file freely):
# this is the code which can change frequently
# and does not need to be marked executable...
print("Content-type: text/html\n\n")
print("<html><head><title>Python</title></head>")
print("<body>Hello, World!</body></html>")

Related

Opening Python script mode on a MacBook

I have a MacBook air and have tried opening Python in terminal but when I open it, it opens Python interactive mode. Does anyone know how to open Python script mode please.
I’ve tried typing in things such as Python or Python 3 like safari suggests but that didn’t work.
There is no 'script mode'. You can create a Python script using TextEdit or another editor, save it as myfile.py, and then run it with python myfile.py.
for running what you are calling 'script version' of python you should choose a python file to run and make sure is written in the same or in a compatible version to the python you are running it with (python2, python3)
For running an example script:
python main.py
You need to be in the directory containing the file so make sure you are there before running the command. Using python runs the first version of python you installed, so if you want to use an other you should use:
python2 main.py
python3 main.py
etc
Assuming you've stored your script in a file named itworks.py, the simplest thing is to type the command python3 itworks.py in a terminal window after you've moved to the directory containing the script. Alternatively, you can type python3 followed by a space, then locate your python script in the Finder and drag and drop it into the terminal. This will expand to the full path to the file, allowing you to run a script located elsewhere than your current directory. Don't forget to press return...
In older versions of MacOS you could say python, but that uses python 2 which is no longer supported so you should go with python3 for any new development. (With MacOS Ventura, python 2 seems to have been removed.)
If you have multiple versions of python, you can use the command which -a python3 (or python) to see all versions on your PATH, and the order in which they will be found. PATH works on a first-come-first-served basis, but you can override by using the fully qualified path name to an alternative python.
Yet another solution, for when you want a more permanent script you will use many times in the future, is to use a "shebang" line as the first line of your script. For example, I wrote the following tiny demo:
#!/usr/bin/env python3
print('It works!')
The first line says to parse this script with the first python3 interpreter found in your current environment's PATH. You could replace that with an explicit path such as #!/opt/homebrew/bin/python3. Now make the script executable: chmod a+x itworks.py. You can now run the script from the current directory by typing ./itworks.py. (The leading ./ tells your shell you know it's in the current directory, and is intended as protection against trojan horse scripts.) If you want to be able to use the now-executable script from anywhere, add it to a directory on your path such as /usr/local/bin, and you'll be able to run it by just typing itworks.py.

Bash script to run python script that trigger a c++ executable

I have a c++ code that is compiled and can be executed.
Let's say the output file after compiling is executable.x.
I also have python script that can call this executable and run it.
pythonScript.py:
# lets say the path is absolute for simplicity.
file_path = 'C:/MyProject/code/executable.x'
# I need to pass an argument to main.cpp
subprocess.check_call([file_path, '-switch1'])
I can run the python script from terminal, and it runs the executable without any issue.
Then there is a shell command to run the python script.
myShell.sh
#!/bin/sh
pwd
(cd pythonScriptDirectory && python3 pythonScript.py)
pwd
By running the sh script, it sets the working directory (like how I run python script from terminal), and then it runs the python script. It seems it also finds the executable.x, but it always return with some error.
Is there any suggestion what might be wrong here, or what would be the debugging approach.
The return value specifies the error code 3221225785 in decimal, which is C000 0139 Hex. My assumption is that the executable file can be selected to run, but a working directory issue causes that libraries being used by executable cannot be loaded.
Here is directory structure:

Run terminal script in python?

I am using python and I am trying to run a shell script that is located in another folder I am trying
subprocess.call(['source','../Apps/appName/run'])
Where 'run' is a shell script I wrote and made an executable. But it keeps giving errors such as
No such file or directory or **No such file or directory: "source"
I have also tried the following
subprocess.call(['source','../Apps/appName/run'])
subprocess.call(['source ../Apps/appName/run'])
subprocess.call(['.','../Apps/appName/run'])
I am trying to run the script and leave it alone (as in I do not want any return value or to see what the output of the shell script is.
Thank you in advance
source is a shell builtin that reads a file and interprets the commands in the current shell instance. It's similar to C #include or Python import. You should not be using it to run shell scripts.
The correct way to run a script is to add a shebang like #!/bin/bash to the first line, and chmod +x yourscriptfile. The OS will then consider it a real executable, which can be executed robustly from any context. In Python, you would do:
subprocess.call(['../Apps/appName/run'])
If for whichever reason this is not an option, you can instead explicitly invoke bash on the file, since this is similar to what would happen if you're in bash and type source:
subprocess.call(['bash', '../Apps/appName/run'])

Using a compiled Python shell in Linux

Is it possible to use a "more complex" shell than just a single command shell? We have written a python shell that is a command loop, and it works fine in /etc/passwd like this:
user:x:1000:1000::/home/user:/usr/bin/ourshell.py
Of course the Python file has the shebang line for /usr/bin/python in it. However, we'd like to compile the Python shell into a .pyc file to save a bit of time on execution in login. So, after compiling, I've been trying to "quote" the shell line in /etc/passwd as "python ourshell.pyc", and I even tried making the shell a bash script which simply executes that same command (with the initial arguments).
Of course none of this has worked. When we SSH in, there is always some kind of error. Is there any special trick to what I am trying to do?
CPython's .pyc files are not text, and do not allow use of a shebang line. The traditional method is to have your called script be tiny; it would simply import a module with the rest of the program, which can then be precompiled. For instance, here is the main script of xonsh:
#!/usr/bin/env python3 -u
from xonsh.main import main
main()
This script takes negligible time to compile. It is also possible to run installed modules using -m, but that takes module names, not filenames, so is not suitable for a shebang script.
I suggest to code a small C wrapper program running your python shell.
(notice that execve(2) forbids nested shebang interpreters; I don't know if that applies for your case)
Look into your log files, probably /var/log/messages and /var/log/auth.log
You may also need to explicitly add (the compiled C executable for the wrapper) to /etc/shells; see shells(5)
Look also into scsh.
Your sshd daemon is probably using Linux Plugin Authentification Modules. So read more about PAM.
Create a file /usr/bin/shell_wrapper that contains this one line:
#!/usr/bin/python /usr/bin/ourshell.pyc
The compiled bytecode ourshell.pyc has to live in /usr/bin, or else change the path accordingly. The python path should go to the same version that compiled the bytecode.
Then make sure to have your /etc/passwd use /usr/bin/shell_wrapper for the shell executable:
user:x:1000:1000::/home/user:/usr/bin/shell_wrapper

Raspberry pi Python shebang with cgi server

I am trying to run a local CGI server on my raspberry pi to host a webpage with a single link, that link is to a CGI script which is supposed to trigger another script and then print HTML code to redirect back to the starting page (so that it doesn't hang)
in the servers root directory i have:
index.html
favicon.ico
Server.py
cgi-bin
my server is set up to use the cgi-bin folder for cgi-scripts.
the issue i am having is i cannot seem to make the scripts callable, is so instead of typing "python Server.py" i should be able to type "Server.py"
in order to do this i have tried multiple shebangs:
#!/usr/bin/env python
#!/usr/bin/python
and then called chmod a+x Server.py to mark it as executable, to no avail.
to clarify i am using:
python 2.7.3rc2
standard raspi linux distro "wheezy"
i read in some of the help docs that if the file has DOS style newlines it interferes with the shebang, so i have ensured that they are now MAC style newlines, this still did not work.
to test further i have made a simple python file which contains:
#!/usr/bin/python
print "Hello World!"
saved it as test.py, marked it as executable, and tried:
/test.py
from the command line and i get:
print: bad interpreter: No such file or directory
can someone please tell me where i'm going wrong?
Thanks
James
Try to remove windows line endings in the script. This made it work for me.
E.g. see How to convert Windows end of line in Unix end of line (CR/LF to LF)
For more possible causes of this problem have look at my answer here https://stackoverflow.com/a/65249192/1150303

Categories