"fork and exit" needed?

S

sjdevnull

Vincent said:
Hi

I'm a Python newbie, and would like to rewrite this Perl scrip
to be run with the Asterisk PBX:

http://www.voip-info.org/wiki/view/Asterisk+NetCID

Anyone knows if those lines are necessary, why, and what their
alternative is in Python?
open STDOUT, '>/dev/null';

Either redefine stdout to an open file object for /dev/null or run the
script as "script.py >/dev/null"
fork and exit;
something like:

if os.fork():
sys.exit(0)

Tells the parent to exit after the fork while the child keeps running.
These are both steps in becoming a daemon (the comp.unix.programmer
FAQ, while skewed toward C, explains why some of these steps are
needed).
 
M

Marc 'BlackJack' Rintsch

Anyone knows if those lines are necessary, why, and what their
alternative is in Python?

sys.stdout = open(os.devnull, 'w')

Ciao,
Marc 'BlackJack' Rintsch
 
N

Nick Craig-Wood

Marc 'BlackJack' Rintsch said:
sys.stdout = open(os.devnull, 'w')

This doesn't have the desired effect

If you run this

import os,sys,time
print os.getpid()
sys.stdout = open(os.devnull, 'w')
time.sleep(60)

It prints its pid.

$ ls -l /proc/32004/fd
total 4
lrwx------ 1 ncw ncw 64 Nov 28 09:55 0 -> /dev/pts/17
lrwx------ 1 ncw ncw 64 Nov 28 09:55 1 -> /dev/pts/17
lrwx------ 1 ncw ncw 64 Nov 28 09:55 2 -> /dev/pts/17
l-wx------ 1 ncw ncw 64 Nov 28 09:55 3 -> /dev/null

That quite clearly shows that stdout isn't /dev/null which is required
for proper deamonisation under unix.

I'm not sure how you do open stdout to /dev/null in python though!

I suspect something like this...

import posix
posix.close(1)
posix.open("/dev/null", posix.O_WRONLY)
 
D

Dennis Lee Bieber

If you run this

import os,sys,time
print os.getpid()
sys.stdout = open(os.devnull, 'w')
time.sleep(60)

It prints its pid.
I would hope so, as you performed the print BEFORE reassigning
stdout...

import os,sys,time
print "pre:", os.getpid()
sys.stdout = open(os.devnull, 'w')
print "post:", os.getpid()
time.sleep(60)

(Granted, I'm on WinXP; I also suspect the original stdout is still open
in the background, maybe dualled with stderr?)
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
F

Fredrik Lundh

Nick said:
If you run this

import os,sys,time
print os.getpid()
sys.stdout = open(os.devnull, 'w')
time.sleep(60)

It prints its pid.

and not only that, if you run

print "world",
print "hello"

it prints "hello world" in the wrong order!

</F>
 
N

Nick Craig-Wood

Dennis Lee Bieber said:
I would hope so, as you performed the print BEFORE reassigning
stdout...

import os,sys,time
print "pre:", os.getpid()
sys.stdout = open(os.devnull, 'w')
print "post:", os.getpid()
time.sleep(60)

(Granted, I'm on WinXP; I also suspect the original stdout is still open
in the background, maybe dualled with stderr?)

Yes that is the point - the original stdout is still open.

I don't think this discussion is relevant to windows though - windows
has its own way of making daemons.
 
M

Mitja Trampus

Nick said:
$ ls -l /proc/32004/fd
total 4
lrwx------ 1 ncw ncw 64 Nov 28 09:55 0 -> /dev/pts/17
lrwx------ 1 ncw ncw 64 Nov 28 09:55 1 -> /dev/pts/17
lrwx------ 1 ncw ncw 64 Nov 28 09:55 2 -> /dev/pts/17
l-wx------ 1 ncw ncw 64 Nov 28 09:55 3 -> /dev/null

I'm not sure how you do open stdout to /dev/null in python though!
I suspect something like this...
import posix
posix.close(1)
posix.open("/dev/null", posix.O_WRONLY)

Yes, you're close enough... The explanations are here:
http://www.google.com/search?q=python close stdout,
I like this one in particular:
http://www.python.org/infogami-faq/...sing-sys-stdout-stdin-stderr-really-close-it/

If you explicitly want to leave file descriptors 0-2 present
(Do you gain anything by not closing them? If you know, do
tell...), but pointing do /dev/null, you could do:

null = os.open(os.devnull,os.O_WRONLY)
os.dup2(null,0)
os.dup2(null,1)
os.dup2(null,2)
os.close(null)

Untested.

More info on file descriptors and python here:
http://docs.python.org/lib/os-fd-ops.html

Mitja
 
V

Vincent Delporte

Yes that is the point - the original stdout is still open.

I don't think this discussion is relevant to windows though - windows
has its own way of making daemons.

Thanks everyone. I'll see if the Python script runs OK in an Asterisk
PBX on Linux.
 
N

Nick Craig-Wood

Mitja Trampus said:
Yes, you're close enough... The explanations are here:
http://www.google.com/search?q=python close stdout,
I like this one in particular:
http://www.python.org/infogami-faq/...sing-sys-stdout-stdin-stderr-really-close-it/

If you explicitly want to leave file descriptors 0-2 present
(Do you gain anything by not closing them? If you know, do
tell...),

It is traditional I think...

From the unix FAQ, http://www.erlenstar.demon.co.uk/unix/faq.txt :-

6. `close()' fds 0, 1, and 2. This releases the standard in, out, and
error we inherited from our parent process. We have no way of knowing
where these fds might have been redirected to. Note that many daemons
use `sysconf()' to determine the limit `_SC_OPEN_MAX'. `_SC_OPEN_MAX'
tells you the maximun open files/process. Then in a loop, the daemon
can close all possible file descriptors. You have to decide if you
need to do this or not. If you think that there might be
file-descriptors open you should close them, since there's a limit on
number of concurrent file descriptors.

7. Establish new open descriptors for stdin, stdout and stderr. Even if
you don't plan to use them, it is still a good idea to have them open.
The precise handling of these is a matter of taste; if you have a
logfile, for example, you might wish to open it as stdout or stderr,
and open `/dev/null' as stdin; alternatively, you could open
`/dev/console' as stderr and/or stdout, and `/dev/null' as stdin, or
any other combination that makes sense for your particular daemon.
but pointing do /dev/null, you could do:

null = os.open(os.devnull,os.O_WRONLY)
os.dup2(null,0)
os.dup2(null,1)
os.dup2(null,2)
os.close(null)

Untested.

Ah, dup2() was on the tip of my mind's tongue ;-)

You could write it like this, and then it even works on Windows!

import os
import sys
import time
print os.getpid()
null = os.open(os.devnull,os.O_RDWR)
os.dup2(null, sys.stdin.fileno())
os.dup2(null, sys.stdout.fileno())
os.dup2(null, sys.stderr.fileno())
os.close(null)
print "You won't see this"
print >>sys.stderr, "Or this"
time.sleep(60)
 
V

Vincent Delporte

I'm not sure how you do open stdout to /dev/null in python though!

I suspect something like this...

import posix
posix.close(1)
posix.open("/dev/null", posix.O_WRONLY)

Thanks everyone, but no go :-/ Neither the above nor "sys.stdout =
open(os.devnull, 'w') " trigger the application.

This is a script that is launched by the Asterisk open-source PBX
server when a call comes in. Its goal is to broadcast some messages to
a Windows caller ID application that is installed on all client hosts
so that they know who's calling.

Before I go ask in an Asterisk forum, is there some Python-related
issue that experienced Python developers can spot in this rewrite of a
Perl script that works?

Here's the original Perl script:
http://www.voip-info.org/wiki/view/Asterisk+NetCID

Here's my Python rewrite:
http://codecomplete.free.fr/asterisk/python_cid.txt

Yes, I changed the UDP port from 42685 to 42687 so that my development
client host is the only one getting the broadcast :)

Thank you!
 
V

Vincent Delporte


More information. Here's what Asterisk says when I call in:

*CLI>

-- Executing LookupCIDName("SIP/fxo-0844e458", "") in new stack

-- Changed Caller*ID name to Work

-- Executing AGI("SIP/fxo-0844e458",
"ncid.python.agi|087077XXXX|Bureau Freebox") in new stack

-- Launched AGI Script /var/lib/asterisk/agi-bin/ncid.python.agi
Failed to execute '/var/lib/asterisk/agi-bin/ncid.python.agi': Exec
format error

-- AGI Script ncid.python.agi completed, returning 0

FWIW, I wrote the original in a Windows text editor, and copy-pasted
the script in Asterisk by sshing into the server. CRLF vs. CR issue?
Something else?

Thanks.
 
V

Vincent Delporte

-- Launched AGI Script /var/lib/asterisk/agi-bin/ncid.python.agi
Failed to execute '/var/lib/asterisk/agi-bin/ncid.python.agi': Exec
format error

Stupid me :-/ Forgot the all-important

#!/usr/bin/python

Sorry for the disturbance..
 
V

Vincent Delporte

which is how Linux knows what interpreter to use for the script.

Thanks. That's what I found out after a bit more research. I didn't
pay attention to this because it's not needed to run under Windows,
and I was focusing on the fork() and stdout thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top