1

I read this:

You can use xinetd to add a service starting your python script. The standard input and output will be transmitted over the network on desired port, so you do not need to modify your scripts (input/raw_input and print methods will work fine).

As a result, I'm using a custom xinet service to launch script.py when a TCP connection is established to 192.168.240.37:65123. The behavior is not as desired/expected.

/root/script.py

#! /usr/bin/python
my_name = raw_input("Enter your name: ")
print my_name
quit()

/etc/xinetd.d/netunique-server

service netunique
{
    disable         = no
    id              = netunique-server
    type            = unlisted
    wait            = no
    socket_type     = stream
    protocol        = tcp
    user            = root
    server          = /usr/bin/python
    server_args     = /root/script.py
    port            = 65123
    flags           = IPv4 REUSE
    bind            = 192.168.240.37
}

systemctl status xinetd

Nov 11 21:24:00 netunique.ourhome.com xinetd[2161]: xinetd Version 2.3.15 started with libwrap loadavg labeled-ne... in.
Nov 11 21:24:00 netunique.ourhome.com xinetd[2161]: Started working: 1 available service

telnet 192.168.240.37 65123 (expected behavior)

[root@netunique xinetd.d]# telnet 192.168.240.37 65123
Trying 192.168.240.37...
Connected to 192.168.240.37.
Escape character is '^]'.
Enter your name: John Smith          <-- I type name after prompt here
John Smith                           <-- Script prints entry back to screen
Connection closed by foreign host.   <-- Script does its quit()   

telnet 192.168.240.37 65123 (actual behavior)

[root@netunique xinetd.d]# telnet 192.168.240.37 65123
Trying 192.168.240.37...
Connected to 192.168.240.37.
Escape character is '^]'.
<blank>                              <-- no prompt as expected
John Smith                           <-- I enter some data and hit Enter
Enter your name: John Smith          <-- Hard to tell exactly what happened here
Connection closed by foreign host.   <-- Hard to tell exactly what happened here
[root@netunique xinetd.d]# 

When I say 'hard to tell exactly what happened here', I mean it's hard to tell if in the above output the 'John Smith' which shows up after the 'Enter your name: ' prompt is a result of the print statement and hard to tell if the 'Connection closed by foreign host' is a result of the quit() statement.

nc 192.168.240.37 65123 (actual behavior)

[root@netunique xinetd.d]# nc 192.168.240.37 65123
<blank>                              <-- no prompt as expected
John Smith                           <-- I enter some data and hit Enter
Enter your name: John Smith          <-- Hard to tell exactly what happened here
                                     <-- Nothing happened here, I hit Enter
                                     <-- I hit Enter again
Ncat: Broken pipe.                   <-- This is the end result

As you can see I get very similar behavior with netcat.

Dan
  • 331
  • 6
  • 17
  • If I remove the "raw_input" from my script and just put in: print 'hello world' this works just fine. It seems to not like the raw_input. Unsure why. – Dan Nov 12 '17 at 02:59
  • What I'm thinking is the XINETD process calls script.py and the commands inside the script are returned across the network connection to the user. When those commands involve raw_input, this requires user interaction, only the network socket on the client side belongs to telnet, it's not a python process, so it probly doesn't know how to interpret or otherwise handle the raw_input request. So it just hangs there rather than displaying text. While telnet to IP:port can execute a script (tasks on the server), I'm not sure this can be used for an interactive script. – Dan Nov 14 '17 at 03:13
  • Basically the client side is 'telnet' and the server side is 'python', so when python sends "raw_input" back to telnet, telnet doesn't know what to do with it. That's what I think is going on. Normally telnet-client talking to telnet-server is an interactive experience, but telnet-client talking to python-script probably is not. – Dan Nov 14 '17 at 03:34
  • You know, your situation looks pretty similar to https://stackoverflow.com/questions/7193738/python-xinetd-client-not-receiving-data Maybe when you open a connection to xinted you need to send an opening line to kick off the script. Could you try your telnet option and then hit enter. Is there any opportunity to enter data after if comes up with the prompt, or does it just die. – Jeff Richards Nov 14 '17 at 05:40
  • Rethinking: server-side python interpreter handles raw_input command, that's where script executes, not client side. Client should only input data across the connection. Yes it seems I'm not able to "kick off" the script. Hitting enter after telnet connection opens causes it to die (see "telnet 192.168.240.37 65123 (actual behavior)" above). I tried printing a string with \n at the end, no improvement. I tried a sleep timer before and after the raw_input prompt, no improvement. Based on the link you sent, seems like kyle's server-side was set up different (sockets). Maybe my problem... – Dan Nov 14 '17 at 07:24
  • Problem: my lack of socket programming functionality. I found this post: https://mail.python.org/pipermail/python-list/2007-July/423659.html – Dan Nov 14 '17 at 07:32
  • Good work figuring it out! – Jeff Richards Nov 14 '17 at 14:51

1 Answers1

2

The real problem for me is apparently my lack of socket programming knowledge. I found this post online searching for "xinetd python no data" (https://mail.python.org/pipermail/python-list/2007-July/423659.html) which helped me at least get my stuff working and sort of illustrated via example a bit about how socket programming actually works. The solution is below, I removed the raw_input from the original script and replaced it with concepts from the post.

/root/script.py (original)

#! /usr/bin/python
my_name = raw_input("Enter your name: ")
print my_name
quit()

/root/script.py (modified & working)

#! /usr/bin/python
import sys
print "Enter your name:"                
sys.stdout.flush()
my_name = sys.stdin.readline().strip()
print "Your name is %s" % my_name
sys.stdout.flush()
quit()

telnet 192.168.240.37 65123 (actual behavior - working)

[root@netunique ~]# telnet 192.168.240.37 65123
Trying 192.168.240.37...
Connected to 192.168.240.37.
Escape character is '^]'.
Enter your name:
Bob Smith
Your name is Bob Smith
Connection closed by foreign host.
Dan
  • 331
  • 6
  • 17
  • The key thing that makes this work is the `sys.stdout.flush()`. Without it, the server-side OS just buffers the text in case you want to send some more. It'll 'flush' it to the network when you explicitly tell it to, or you implicitly tell it to by sending a `\n`. – Ralph Bolton Dec 05 '17 at 12:20
  • using python's `print` appends a newline, doesn't it? – Benni Sep 27 '19 at 11:00