Search code examples
pythonsubprocesscgiwgetos.system

using os.system() in a python cgi script


I'm building a cgi script with python on my web host and using wget to test it. The shebang #!/home/me/virtualenv/public_html/chartex/3.6/bin/python3.6 points it at the right version of python to use so that print(sys.version, sys.executable) in the cgi correctly returns:

3.6.15 (default, Jan 14 2022, 12:16:54) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] /home/me/virtualenv/public_html/chartex/3.6/bin/python3.6_bin

Moreover print(os.path.abspath('.')) in the cgi returns the correct path to where the script resides.

However, if I want the cgi to report the version of an existing binary on the system print(os.system('twopi -V')) returns only 0. The same thing happens doing print(os.system('ls')).

If I run the same python installed in this virtualenv (calling it by its full pathname on the server) at the command line, and there call print(os.system('twopi -V')), it correctly tells me: twopi - graphviz version 4.0.0 (20220529.0937) and then on the next line: 0. Likewise if I do print(os.system('ls'))

Is this kind of system command impossible for a cgi script? Is there a way I can coerce the script to report the result of such a system command?


Solution

  • In case anyone is similarly confused about subprocess:

    Thanks to the observations of @furas and a great deal of messing about with subprocess I finally figured out an incantation that would compel my python2.7 cgi script to give me the shell output of the command twopi -V. A comment from @tripleee in this thread was the key. For Python 3.7.9 and up: "capture_output is a shorthand for the option combination stdout=supprocess.PIPE, stderr=subprocess.PIPE

    p = subprocess.Popen(['twopi', '-V'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print("stderr:  " + p.stderr.read())
    print("stdout:  " + p.stdout.read())
    # with the result:
    stderr:  twopi - graphviz version 4.0.0 (20220529.0937)
    stdout:  
    
    

    The actual shell output was going to stderr. The subprocess module is byzantine! It's a little better under python3, but not much.