1

I am generating HTML page from Python. There is also logic for spawning a SSH session using pexpect and fetching command output inside same Python code. But when I run Python from Apache httpd server, it is giving me 500 internal server error. But executing Python code separately is working fine.

Not sure if issue is in Python or Apache?

Code is below and I have added the exception for debugging purpose. Exception shows

Exception seen in Web page :
Error! pty.fork() failed: out of pty devices name 
'child' is not defined name 
'child' is not defined name 
'child' is not defined name 
'child' is not defined name 
'child' is not defined name 
'child' is not defined name 
'child' is not defined name

Code is below #############################################################

import pexpect
import sys
import time
import cgi, cgitb
import getpass
print "Content-Type: text/html\n\n"

try:
        child = pexpect.spawn('ssh -t admin@192.***.***.*** login root')
except Exception, e:
        print e
try:
        child.expect('(?i)password')
except Exception, e:
        print e
try:
        child.sendline('password')
except Exception, e:
        print e
try:
        child.expect('(?i)Password:')
except Exception, e:
        print e
try:
        child.sendline('password')
except Exception, e:
        print e
try:
        child.expect('-bash# ')
except Exception, e:
        print e
try:
        child.sendline('ls -al')
except Exception, e:
        print e
try:
        child.expect('-bash# ')
except Exception, e:
        print e
output = child.before
print "Content-Type: text/html\n\n"
print "<html>"
print "<head>"
print "<title>Hello </title>"
print "</head>"
print "<body>"
print "<h1>",output,"</h1>"
print "</body>"
print "</html>"
NoviceInPython
  • 113
  • 1
  • 2
  • 9
  • Catch and display all exceptions from your pexpect code. It could be that your ssh session isn't working as the apache www-data user. For instance, it typically doesn't have ~/.ssh/* files. – tdelaney Mar 27 '14 at 23:21
  • I am executing this script just by saving it in /var/www/cgi-bin folder. calling it as localhost/cgi-bin/test1.py plain cgi " malformed header from script. Bad header=name 'child' is not defined: test1.py", is seen in error_log child is handler for session spawned – NoviceInPython Mar 27 '14 at 23:34
  • could you edit your post and paste the code of your script? – b2Wc0EKKOvLPn Mar 28 '14 at 00:00
  • Are you returning http + html? When running as a cgi script, your python output should include http header lines (e.g., "Content-Type: text/html") followed by a blank line and then the html. – tdelaney Mar 28 '14 at 00:13
  • The [cgi module](http://docs.python.org/2/library/cgi.html) may help. – tdelaney Mar 28 '14 at 00:15
  • @tdelaney Yes, I am adding the header. – NoviceInPython Mar 28 '14 at 00:24
  • 1
    Its a system problem - you've gone over max ptys for all programs. /proc/sys/kernel/pty/nr is current allocation, /proc/sys/kernel/pty/max is max. You can do `ls /dev/pts` and do `lsof /dev/pts/one-of-the-numbers` to get an idea who's using them. it may be old versions of your program that have hung. Kill old ones if they are still there. And add a timeout to your spawn call `pexpect.spawn('ssh -t admin@192.***.***.*** login root', timeout=30)` – tdelaney Mar 28 '14 at 04:05
  • for nr and max number commands I am getting permission denied. lsof command is not found – NoviceInPython Mar 28 '14 at 07:45
  • 1
    Ouch. sounds like this is a locked down system... perhaps you don't have rights to create any ptys and that means you can't use pexpect. If you don't need an interactive session, try the python paramiko module and its exec_command method. – tdelaney Mar 28 '14 at 15:39
  • I have root privileges and logging as root. I should be having permissions to create ptys – NoviceInPython Mar 28 '14 at 18:00
  • Were you able to figure this out? – Federico Jan 20 '16 at 22:54
  • It's most likely a selinux problem. Have a look at http://stackoverflow.com/questions/6954285/apache-pty-errors-in-cgi-perl-file-while-creating-a-new-expect-object – Federico Jan 21 '16 at 00:36

1 Answers1

0

The child variable is defined in the scope of the first try block. When it goes out of the scope of the first try block it becomes unknown to the interpreter. You could fix this by merging all your try blocks into one. Which is enough.

Try with this snippet:

#!/usr/bin/env python

import pexpect
import sys
import time
import cgi, cgitb
import getpass


output = ""
try:
        child = pexpect.spawn('ssh -t admin@192.***.***.*** login root')
        child.expect('(?i)password')
        child.sendline('password')
        child.expect('(?i)Password:')
        child.sendline('password')
        child.expect('-bash# ')
        child.sendline('ls -al')
        child.expect('-bash# ')
        output = child.before
except Exception, e:
    print e

print "Content-Type: text/html\n\n"
print "<html>"
print "<head>"
print "<title>Hello </title>"
print "</head>"
print "<body>"
print "<h1>",output,"</h1>"
print "</body>"
print "</html>"
b2Wc0EKKOvLPn
  • 2,054
  • 13
  • 15
  • Thank You ! Yes, I did try in the above manner and it is still saying **"Error! pty.fork() failed: out of pty devices"** – NoviceInPython Mar 28 '14 at 01:25
  • Have a look at [this](http://stackoverflow.com/questions/8561121/troubleshooting-oserror-out-of-pty-devices). It might help you. – b2Wc0EKKOvLPn Mar 28 '14 at 01:42
  • Thanks! for your help all through. I have tried that page it is not useful. – NoviceInPython Mar 28 '14 at 01:54
  • Try restarting whatever you'r remote-connecting to if you can afford to do it. That would give you a baseline to start from again and see if the problem persists. – b2Wc0EKKOvLPn Mar 28 '14 at 01:58
  • I do not have the access to restart the remote machine. – NoviceInPython Mar 28 '14 at 02:13
  • @ylabidi: try blocks do not create a new scope: if the value is assigned, it can be accessed later outside that block. The change you suggest makes sense, but the reason is that if `spawn` fails, there's no `child` variable to use, so you want to jump out of the block that uses it. – Thomas K Mar 28 '14 at 17:41