Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

daemons in TCL

104 views
Skip to first unread message

Paul Argentoff

unread,
Jan 6, 1999, 3:00:00 AM1/6/99
to
Hi ALL!

Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
to tell the program to fork() to background and do the job there?
--
Best regards, -- Paul. ICQ 20249720

Alexandre Ferrieux

unread,
Jan 6, 1999, 3:00:00 AM1/6/99
to
Paul Argentoff wrote:
>
> Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
> to tell the program to fork() to background and do the job there?

Easier yet, ask the calling shell to do it:

#! /bin/sh
#\
tclsh $0 "$@" & exit 0

# Tcl code here

-Alex

Tom Poindexter

unread,
Jan 6, 1999, 3:00:00 AM1/6/99
to
In article <m3sodo1...@HAL9000.intranet.max>,
Paul Argentoff <fu...@dol.ru> wrote:
>Hi ALL!

>
>Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
>to tell the program to fork() to background and do the job there?


Extended Tcl (TclX) has all the commands you need to do the job:
fork, signal, id process umask, wait, dup, etc.

Here are few snippets of code that I've used in the past, it's not
complete, but you should get an idea of what is possible. This code is
from a load balancing report scheduler that I wrote a while back for a client,
getting user report requests through a database. 'daemonize' and signal
catching is probably the code for which you're looking, but other parts that
exec other programs and wait on their completion might be useful.

The 'daemonize' code is based on the C code from Richard Steven's
most excellent book, "Unix Network Programming".

Other TclX commands are also used throughout the code: lassign, clength,
cequal, fmtclock, etc.


#############################################################################
# global data structures

global outdir ; set outdir /tmp ;# output file directory
global logdir ; set logdir /tmp ;# logging dir
global logfile ; set logfile "" ;# logfile name
global logfd ; set logfd "" ;# logfile fd
global ridqueue ; set ridqueue "" ;# current request queue
global execinfo ; set execinfo(x) "" ;# current executing info


#############################################################################
# logentry - record info

proc logentry {args} {
global logfile
global logfd
global logdir

set now [getclock]
set dt [fmtclock $now "%Y.%m.%d"]
set tm [fmtclock $now "%T"]

if {[string compare $dt $logfile] != 0} {
catch {close $logfd}
set logfile $dt
set logfd [open $logdir/$logfile a]
}

puts $logfd "$dt $tm $args"
flush $logfd

}

#############################################################################
# start execution - fork and start sh job, return pid

proc start {rid cmdline outfile userid deliv_type deliv_node} {
global execinfo

set pid [fork]
if {$pid} {
# parent
set execinfo($rid,pid) $pid
set execinfo($rid,outfile) $outfile
set execinfo($rid,cmdline) $cmdline
set execinfo($rid,userid) $userid
set execinfo($rid,status) ""
set execinfo($rid,dtype) $deliv_type
set execinfo($rid,dnode) $deliv_node
return $pid
} else {
# child
global errorCode
set errorCode 0
catch {exec /bin/sh -c "$cmdline $rid $outfile" >& /dev/null < /dev/null}
exit $errorCode
}
}

#############################################################################
# repo man - reap process, return rid that finished

proc repoman {} {
global ridqueue
global execinfo

if {[lempty $ridqueue]} {
return -1
}
set inf ""
catch {set inf [wait -nohang]}
if {[clength $inf] > 0} {
lassign $inf pid type val
# find request id for this pid
set idx 0
foreach rid $ridqueue {
if {[cequal $pid $execinfo($rid,pid)]} {
if {[cequal $type EXIT]} {
set execinfo($rid,status) $val
} elseif {[cequal $type SIG]} {
set execinfo($rid,status) -1
}
logentry process finished $rid pid: $pid status $val
return $rid
}
incr idx
}
}
return -1
}

#############################################################################
# completion - record completion info

proc completion {} {
global execinfo
global ridqueue

set rid [repoman]
if {$rid == -1} {return 0}

if {$execinfo($rid,status) == 0} {
# log completion
set outfile $execinfo($rid,outfile)
logentry request $rid completed, $execinfo($rid,outfile)
# notify completion
logentry request $rid: emailing $execinfo($rid,userid) completion
set dt [fmtclock [getclock]]
catch {exec mailx $execinfo($rid,userid) << \
"job $execinfo($rid,outfile) request $rid completed $dt "}
} else {
logentry request $rid failed, status $execinfo($rid,status)
}

set idx [lsearch $ridqueue $rid]
set ridqueue [lreplace $ridqueue $idx $idx]

unset execinfo($rid,cmdline)
unset execinfo($rid,userid)
unset execinfo($rid,outfile)
unset execinfo($rid,pid)
unset execinfo($rid,status)
unset execinfo($rid,dtype)
unset execinfo($rid,dnode)

return $rid
}

#############################################################################
# dispatcher - look for work, start jobs, record finish

proc dispatcher {} {
global ridqueue

while 1 {

# check for completed jobs
logentry scan competion queue tick
while {[set rid [completion]]} {
logentry completion for $rid
}

# here is where jobs get started
# i've omitted the code that determines which jobs to run, etc.
start $rid $cmdline $outfile $userid $deliv_type $deliv_node

# sleep at little
sleep 30
}
}


#############################################################################
# shutdown - graceful shutdown on sigterm

proc shutdown {} {
global ridqueue
global execinfo
global logfd

logentry shutdown started
# kill any jobs that might be running
foreach rid $ridqueue {
catch {
logentry killing $execinfo($rid,pid)
kill $execinfo($rid,pid)
unlink -nocomplain $execinfo($rid,outfile)
}
}
catch {close $logfd}
exit
}


#############################################################################
# daemonize - see r.stevens "unix network programming"

proc daemonize {} {
close stdin
close stdout
close stderr
if {[fork]} {exit 0}
id process group set
if {[fork]} {exit 0}
set fd [open /dev/null r]
set fd [open /dev/null w]
set fd [open /dev/null w]
cd /
umask 022
return [id process]
}


#############################################################################
# main code, become daemon, catch signals, and look for work

set p [daemonize]
signal ignore SIGHUP
signal unblock {QUIT TERM}
signal trap {QUIT TERM} shutdown

logentry sched startup, pid: $p

# start the dispatcher
dispatcher

# which should not return, if it does, then

logentry oops!! sched failed unexpectedly
shutdown


--
Tom Poindexter
tpoi...@nyx.net
http://www.nyx.net/~tpoindex/
--
Tom Poindexter
tpoi...@nyx.net
http://www.nyx.net/~tpoindex/

Alexandre Ferrieux

unread,
Jan 7, 1999, 3:00:00 AM1/7/99
to
Tom Poindexter wrote:
>
> In article <m3sodo1...@HAL9000.intranet.max>,
> Paul Argentoff <fu...@dol.ru> wrote:
> >Hi ALL!
> >
> >Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
> >to tell the program to fork() to background and do the job there?
>
> Extended Tcl (TclX) has all the commands you need to do the job:
> fork, signal, id process umask, wait, dup, etc.
>
> Here are few snippets of code that I've used in the past, it's not
> complete, but you should get an idea of what is possible.

Do you intendedly suggest this far-fetched solution, involving an
extension, while a one-liner shell solution exists (and even within
tclsh itself with [exec tclsh ... &]) ?

-Alex

Steve Ball

unread,
Jan 7, 1999, 3:00:00 AM1/7/99
to
Paul Argentoff wrote:
> Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
> to tell the program to fork() to background and do the job there?

tclhttpd is perhaps the most simple, yet impressive, Tcl-based daemon code I've
seen to date. http://www.scriptics.com/ is where it lives (and runs!)

Forking a process is actually not the Tcl way of doing things. Better to
not fork at all and do event-driven programming with asynchronous I/O instead.
My forthcoming book, Web Tcl Complete (yes folks, it's still coming ;-),
has a whole chapter on the subject. Drafts are at http://www.zveno.com/zm.cgi/in-wtc/

HTHs,
Steve Ball

Alexandre Ferrieux

unread,
Jan 7, 1999, 3:00:00 AM1/7/99
to
Steve Ball wrote:
>
> Forking a process is actually not the Tcl way of doing things. Better to
> not fork at all and do event-driven programming with asynchronous I/O instead.
> My forthcoming book, Web Tcl Complete (yes folks, it's still coming ;-),
> has a whole chapter on the subject. Drafts are at http://www.zveno.com/zm.cgi/in-wtc/

Shameless plug. When you're a WWW hammer, everything looks like a WWW
nail.
FYI, "daemon" is slightly more general than "TCP server"...

Though you're right to point out the power of the event-driven model,
forking(and execing) a process happens to fit quite nicely into Tcl too
(exec & and open "|...").

-Alex

Tom Poindexter

unread,
Jan 7, 1999, 3:00:00 AM1/7/99
to
In article <36947E...@cnet.francetelecom.fr>,

Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
>Tom Poindexter wrote:
>> In article <m3sodo1...@HAL9000.intranet.max>,
>> >Has anybody any idea on how to write a sort of daemon in TCL? I mean, how
>> >to tell the program to fork() to background and do the job there?
>>
>> Extended Tcl (TclX) has all the commands you need to do the job:
>> fork, signal, id process umask, wait, dup, etc.

>Do you intendedly suggest this far-fetched solution, involving an


>extension, while a one-liner shell solution exists (and even within
>tclsh itself with [exec tclsh ... &]) ?


I didn't see a smiley, so I'll explain my "far-fetched solution" and
why your one-liner is not a daemon.

Daemons in Unix usually refer to specific programming models. Daemons
must go to extra steps to disassociate with a control tty, and become it's own
process group leader. Otherwise, 'ill-formed' daemons are subject to
signals assosciated with your tty.

As I've mentioned in my previous post, Richard Stevens'
"Unix Network Programming" and "Advanced Unix Programming" texts go into
detail of the why's and wherefor's of daemons. Highly recommended reading
for anyone writing daemons or other system code in Unix.

Background execution by shells is also dependent on the behavior of
any particular shell. On my Solaris 2.5 box, classic Bourne shell /bin/sh
doesn't protect background processes from HANGUP and QUIT signals. Korn93
/bin/ksh does.

Here are two examples:

daemon1.tcl----------------------------------------------------------
#! /bin/sh
#\
tclsh8.0 $0 "$@" & exit 0
# Tcl code here
while 1 {
set fd [open /tmp/daemon1.log w]
puts $fd "daemon1.tcl last ran at [clock format [clock seconds]]"
close $fd
after 5000
}


daemon2.tcl----------------------------------------------------------
#!/home/tpoindex/bin/tclsh8.0
package require Tclx
proc shutdown {} {
# whatever cleanup you need to do
exit
}
proc dispatcher {} {
while 1 {
set fd [open /tmp/daemon2.log w]
puts $fd "daemon2.tcl last ran at [clock format [clock seconds]]"
close $fd
after 5000


}
}
proc daemonize {} {
close stdin
close stdout
close stderr
if {[fork]} {exit 0}
id process group set
if {[fork]} {exit 0}
set fd [open /dev/null r]
set fd [open /dev/null w]
set fd [open /dev/null w]
cd /
umask 022
return [id process]
}

daemonize
signal ignore SIGHUP
signal unblock {QUIT TERM}
signal trap {QUIT TERM} shutdown

dispatcher


Start both examples and logout. If you're running under Ksh, it is
likely that both will still be running when you log back in. Under
/bin/sh, it's extremely likely that only daemon2.tcl will be left
running.

daemon2.tcl works no matter what shell you are running under.

And one the subject of extensions, I'll gladly use one that
provides features that are not present in vanilla Tcl.
TclX, Expect, et.al., each provide me with things I can't do
in Tcl.

Cameron Laird

unread,
Jan 7, 1999, 3:00:00 AM1/7/99
to
In article <3694B5...@cnet.francetelecom.fr>,

I think all you guys--Alex, Tom, and Steve--are funny.
Funny in a good way. That is, when I read a non-native
speaker asking for "a sort of daemon in TCL", my first
thought is, "I wonder what he really wants?" You three
have more courage and/or intuition than I do, 'cause you
all wrote interesting and accurate responses that taught
*me* a few things. I'm fascinated to learn what use
the original poster will make of them.
--

Cameron Laird http://starbase.neosoft.com/~claird/home.html
cla...@NeoSoft.com +1 281 996 8546 FAX

Alexandre Ferrieux

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to
Tom Poindexter wrote:
>
> Daemons in Unix usually refer to specific programming models. Daemons
> must go to extra steps to disassociate with a control tty, and become it's own
> process group leader. Otherwise, 'ill-formed' daemons are subject to
> signals assosciated with your tty.

Yessir. And all this is supposed to be handled by stuff like 'nohup' and
'&'.
I've not used 'nohup' in my example because I had the vague memory that
all modern shells nohup-ed by default when using '&'. Can you give me an
update ?

> On my Solaris 2.5 box, classic Bourne shell /bin/sh
> doesn't protect background processes from HANGUP and QUIT signals. Korn93
> /bin/ksh does.

Not here. I mean, on my Sol2.5 your daemon1.tcl example happily
survives logout.
Now I know that *csh* does nohup its background children, but here the
csh launches the sh in foreground, and the sh does the '&'. Or is it
that csh nohups (signal(SIGHUP,SIGIGN)) also its foreground children ?
In that case, on systems where the SIGHUP part of the signal mask is
inherited, the early presence of a csh in the hierarchy explains the
implicit nohup.

So anyway, can you now tell me in what situations the following will
fail:

#! /bin/sh
#\
nohup tclsh $0 "$@" & exit 0

-Alex

Tom Poindexter

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to
In article <3695DF...@cnet.francetelecom.fr>,
Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:

>I've not used 'nohup' in my example because I had the vague memory that
>all modern shells nohup-ed by default when using '&'. Can you give me an
>update ?

I just wouldn't make the assumption that everyone is running
a modern shell. A daemon is often started at boot time, where /bin/sh
is often the shell of choice.

How various shells handle & is probably a better question
for comp.unix.*. I haven't dug into that type of code for several years,
and I still consider Stevens a defintive guide on the subject.

Alexandre Ferrieux

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to

Would you be so kind as to reply to the 'nohup' suggestion (still a
one-liner)?

-Alex

Tom Poindexter

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to
In article <369630...@cnet.francetelecom.fr>,

Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
>Would you be so kind as to reply to the 'nohup' suggestion (still a
>one-liner)?

You are free to use nohup. For code I write and is used by others, I'll
continue to use TclX.
Best.

lvi...@cas.org

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to

According to Paul Argentoff <fu...@dol.ru>:
:Has anybody any idea on how to write a sort of daemon in TCL? I mean, how

:to tell the program to fork() to background and do the job there?

You might take a look at
<URL: http://www.purl.org/NET/Tcl-FAQ/part4.html> as I believe
there are a couple of tcl code daemons listed there.

--
<URL: mailto:lvi...@cas.org> Quote: Saving the world before bedtime.
<*> O- <URL: http://www.purl.org/NET/lvirden/>
Unless explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.

David May

unread,
Jan 9, 1999, 3:00:00 AM1/9/99
to
In article <91581508...@iris.nyx.net>,

tpoi...@nyx10.nyx.net (Tom Poindexter) writes:
> In article <369630...@cnet.francetelecom.fr>,
> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
>>Would you be so kind as to reply to the 'nohup' suggestion (still a
>>one-liner)?
>
> You are free to use nohup. For code I write and is used by others, I'll
> continue to use TclX.
> Best.
>

My main use for Tcl is network programming tasks and I have written a number
of Tcl based daemons.

I agree with Tom Poindexter - just using & and nohup cannot turn a Tcl
script into a true daemon process. Refer to Stevens "Advanced Network
Programming" to find out the details.

What I generally do is write a C stub which contains the daemonizing
code and all the other systems programming things core Tcl cannot handle
and then exec the Tcl script to handle the main event loop.

If you all you really need is a long lived background process then maybe
& and nohup are sufficient.

Troy Hanson

unread,
Jan 9, 1999, 3:00:00 AM1/9/99
to
David May wrote:
> I agree with Tom Poindexter - just using & and nohup cannot turn a Tcl
> script into a true daemon process. Refer to Stevens "Advanced Network
> Programming" to find out the details.

I'm curious... I've written Tcl daemons myself. If the Tcl daemon is started
by init (i.e., the Tcl script has an entry in /etc/inittab) then isn't it
automatically dissociated from a controlling tty? Is is subject to any signals
that still necessitates the fork()/setsid() sequence recommended by Stevens?

Troy Hanson

Tom Poindexter

unread,
Jan 9, 1999, 3:00:00 AM1/9/99
to
In article <36978BCF...@goldengate.net>,

Troy Hanson <tha...@goldengate.net> wrote:
>I'm curious... I've written Tcl daemons myself. If the Tcl daemon is started
>by init (i.e., the Tcl script has an entry in /etc/inittab) then isn't it
>automatically dissociated from a controlling tty? Is is subject to any signals
>that still necessitates the fork()/setsid() sequence recommended by Stevens?

Stevens makes special mention of daemons started from inittab on pg 80-81 of
"Unix Network Programming", espcially when the inittab action is respawn.
Since init will watch and restart processes that end, a daemon started by
init shouldn't fork, because as soon as the parent exits, init will restart it,
your daemon will fork, parent exit, restart, etc. until you run out
of resources.

It's probably still prudent to either call setsid() or setpgrp(). TclX's
'id process group set' command invokes the later. And of course, your daemon
should still handle signals gracefully, set an appropriate umask, etc.
A root user typically sends SIGHUP (kill -1 1) to cause init to re-read
/etc/inittab; I'd have to review init source to see if it ingores SIGHUP
for processess it forks off.

To TclX guys Mark/Karl: if either of you are following this thread, how about
adding 'id process session set' to call setsid() on systems that support it?
I'll be glad to send a patch if you dont' have time.

Troy Hanson

unread,
Jan 9, 1999, 3:00:00 AM1/9/99
to
Tom Poindexter wrote:
> Stevens makes special mention of daemons started from inittab on pg 80-81 of
> "Unix Network Programming", espcially when the inittab action is respawn.

Very interesting. About respawn, I learned "the hard way" that the recommended
daemon startup of fork()/exit() didn't apply to daemons with the respawn
action. (Wish I'd read Stevens before that :). After starting about ten
copies of my daemon, init finally gave up and printed a message on the console
about "process exiting too quickly" or something. Kudos to init for not
starting it ad infinitum, and for the descriptive error message.

The other reason your response is interesting, is that my Stevens' "Unix
Network Programming" Volume 1, Second edition, seems to be different from
yours. Page 80-81 in my volume talks about readline and isfdtype. I wonder if
you have the first edition?

> It's probably still prudent to either call setsid() or setpgrp().

In my most recent daemon, written in C, I eventually commented out my call to
setsid() because, when manually started from the shell, it gets an error result
from setsid(). I don't know if the same error would occur if the daemon was
started by init; I just left setsid() commented out. I know Stevens makes some
comments about fork/parent-exit being a "prerequisite" for the call to setsid.
Since I'd removed the fork/parent-exit I guess he was right. I'm far from an
expert on signal handling's relationship to session/process-group id. I was
using SCO Unix by the way.

Troy

Alexandre Ferrieux

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
Tom Poindexter wrote:
>
> In article <369630...@cnet.francetelecom.fr>,
> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> >Would you be so kind as to reply to the 'nohup' suggestion (still a
> >one-liner)?
>
> You are free to use nohup. For code I write and is used by others, I'll
> continue to use TclX.
> Best.

You are not arguing much. Or are you only interested in selling the book
:^) ?

Seriously, you seem to have a better understanding of the details here.
Please share it: in what precise conditions will a nohup ... & fail ?

-Alex

Tom Poindexter

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
In article <3697BDBA...@goldengate.net>,

Troy Hanson <tha...@goldengate.net> wrote:
>Tom Poindexter wrote:
>> Stevens makes special mention of daemons started from inittab on pg 80-81 of
>> "Unix Network Programming", espcially when the inittab action is respawn.
>The other reason your response is interesting, is that my Stevens' "Unix
>Network Programming" Volume 1, Second edition, seems to be different from
>yours. Page 80-81 in my volume talks about readline and isfdtype. I wonder if
>you have the first edition?

Oops, yes, 1st edtion, circa 1992 or so.

>> It's probably still prudent to either call setsid() or setpgrp().
>
>In my most recent daemon, written in C, I eventually commented out my call to
>setsid() because, when manually started from the shell, it gets an error result
>from setsid(). I don't know if the same error would occur if the daemon was
>started by init; I just left setsid() commented out. I know Stevens makes some


Stevens' "Advanced Programming in the Unix Environment" goes into more
length about setsid(), and the daemonize() function he presents in APUE is
different than in UNP. setsid() will fail if the process is already a
process group leader. As Alexandre implies in his posts, your
shell is probably calling setpgrp() after it forks.

Tom Poindexter

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
In article <3699C7...@cnet.francetelecom.fr>,

Actually I made my points; apparently your system uses different
shells, and you are not able to reproduce the situation.

My point is that 'nohup ... &' is dependent on your shell. Here's an
example:

xxxxxxxxx/home/tpoindex: ls -l /bin/sh /bin/ksh
-r-xr-xr-x 2 bin bin 180856 Oct 25 1995 /bin/ksh
-r-xr-xr-x 3 bin root 87012 Oct 25 1995 /bin/sh

Ok, Ksh is really different from Bourne shell on my system. Start up
Bourne shell:

xxxxxxxxx/home/tpoindex: exec /bin/sh
$HOSTN${PWD##}:

Here's my current version of daemon1.tcl:

$HOSTN${PWD##}: head -4 daemon1.tcl
#! /bin/sh
#\
nohup tclsh8.0 $0 "$@" </dev/null >/dev/null 2>/dev/null & exit 0
# Tcl code here


Start up daemon1.tcl:

$HOSTN${PWD##}: daemon1.tcl
$HOSTN${PWD##}: ps -f | grep daemon1
tpoindex 12293 12260 0 08:59:15 pts/5 0:00 grep daemon1.tcl
tpoindex 12292 1 2 08:59:11 pts/5 0:00 tclsh8.0 ./daemon1.tcl


Now send a signal to the process group of my shell. I'm picking SIGTERM (say
you have some errant process, and the system admin kills your shell.) Notice
I'm not sending the signal to the daemon1.tcl itself, just the process
group of the shell:

$HOSTN${PWD##}: echo $$
12260
$HOSTN${PWD##}: /bin/kill -15 -12260
Terminated


Now, check if daemon1 is still running:
$HOSTN${PWD##}: ps -f | grep daemon1
tpoindex 12303 12260 0 09:03:41 pts/5 0:00 grep daemon1

Nope, it gone :-(

Now try the same exercise with my daemon2.tcl. Since daemon2.tcl
explicitly sets its process group, it is no longer dependent on
your shell.

> You are not arguing much. Or are you only interested in selling the book
> :^) ?

If I had any connection with W. Richard Stevens or his publisher, I would
disclose that fact. I don't.

In my opinion, Stevens is a wonderful writer on this subject (as well as
many other programming and network subjects.)


Hope this helps.

Don Libes

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
In article <3699C7...@cnet.francetelecom.fr> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> writes:
Tom Poindexter wrote:
> In article <369630...@cnet.francetelecom.fr>,

> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> >Would you be so kind as to reply to the 'nohup' suggestion (still a
> >one-liner)?
>
> You are free to use nohup. For code I write and is used by others, I'll
> continue to use TclX.
> Best.

You are not arguing much. Or are you only interested in selling the book
:^) ?

Seriously, you seem to have a better understanding of the details here.
Please share it: in what precise conditions will a nohup ... & fail ?

Here's a simple scenario for which nohup& is insufficient:

User wants to start a process in the background. Process prompts
for password but does no further interaction.

Don

Don Libes

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to

Expect provides "fork" and "disconnect" which do this. Check out
Expect's implementation before reimplementing from scratch as Stevens'
code only works on a subset of systems.

I am of course indebted to Stevens. In fact, comments in the Expect
code reference page numbers in both APUE and UNP because some of the
code comes right from them.

There's a thorough discussion and examples of fork/disconnect in the
Background chapter of EE starting on page 373.

Don

Alexandre Ferrieux

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
Don Libes wrote:

>
> Alexandre Ferrieux writes:
>
> in what precise conditions will a nohup ... & fail ?
>
> Here's a simple scenario for which nohup& is insufficient:
>
> User wants to start a process in the background. Process prompts
> for password but does no further interaction.

Nope, I do this all the time. Simply separate the interactive and
background parts, and use a short-lived 'echo' and a pipe as a
reasonably secure way of transmitting the password (unlike the
environment of course !):


#! /bin/sh
#untcl\
stty -echo > /dev/tty;echo -n "Password: " >/dev/tty;read pass <
/dev/tty;stty echo > /dev/tty;echo $pass | nohup wish $0
>/dev/null & exit 0

gets stdin pass
...

-Alex

Alexandre Ferrieux

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
Tom Poindexter wrote:
>
> Actually I made my points; apparently your system uses different
> shells, and you are not able to reproduce the situation.
> ...

> Now send a signal to the process group of my shell. I'm picking SIGTERM (say
> you have some errant process, and the system admin kills your shell.) Notice
> I'm not sending the signal to the daemon1.tcl itself, just the process
> group of the shell:

Okay, thanks for the precision.

Actually my system (Sol2.5.1) does propagate the SIGTERM in that case. I
only failed to consider this (somebody actively signalling the pgrp with
death in mind) as a normal situation. The only thing I wanted my dameon
to survive was a logout of its owner; that's of course the kind of
robustness (SIGHUP) that nohup is supposed to provide !

Or do you see yet another state of affairs where the system would
'innocently' send a lethal signal to the group ?

-Alex

PS: apart from historical reasons, do you see a reason why a user shell
would want to drag its background children along in its way to the grave
?

Tom Poindexter

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
In article <369B0C...@cnet.francetelecom.fr>,

Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
>
>Or do you see yet another state of affairs where the system would
>'innocently' send a lethal signal to the group ?
...

>PS: apart from historical reasons, do you see a reason why a user shell
>would want to drag its background children along in its way to the grave
>?

I can think of several reasons why you would want this behavior. Here's an
example: you have several mounted file systems, and need to take one offline
for some maintenance. You'll have to terminate any process that still has
a working directory on that file system. It's much easier to kill the
process group leaders and let the signal proprogate the the childern, rather
than to hunt down each individual process.

Don Libes

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to

How do you handle a variable prompt from the program - such as
challenge-response?

Don

Alexandre Ferrieux

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
Tom Poindexter wrote:
>
> I can think of several reasons why you would want this behavior. Here's an
> example: you have several mounted file systems, and need to take one offline
> for some maintenance. You'll have to terminate any process that still has
> a working directory on that file system. It's much easier to kill the
> process group leaders and let the signal proprogate the the childern, rather
> than to hunt down each individual process.

"Much easier ?": Why, since you have to loop on an fuser-generated list
of PIDs anyway ?
Sorry - unconvinced.

-Alex

Alexandre Ferrieux

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to

Again, 'Simply separate the interactive and background parts'.
The interactive part is a one-liner in my example, but could well be
more complex, including a loop of natural language queries (why not a
Turing test ?). When all parameters have been gathered, pack them in a
string, and pass it with the [echo] trick to the bg child (which could
even be the very same script switching behaviors based on an environment
variable).

Or do you mean 'a daemon that, at some late point of its life, suddenly
needs some tty input again' ? Do you realize how far off-topic this is
starting to be ? What kind of daemon is that ? What happens if its
initial launcher has long walked off ?

-Alex

Don Libes

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to

'Simply separate' sounds like 'miracle occurs here'. I don't see how
you can do such a thing for challenge-response programs. Sure, it's
easy for your own programs, but I don't see how you can do it for
programs for which you cannot predict the precise prompt.

Don

Alexandre Ferrieux

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to
Don Libes wrote:
>
> > How do you handle a variable prompt from the program - such as
> > challenge-response?
>
> Again, 'Simply separate the interactive and background parts'.
> The interactive part is a one-liner in my example, but could well be
> more complex, including a loop of natural language queries (why not a
> Turing test ?). When all parameters have been gathered, pack them in a
> string, and pass it with the [echo] trick to the bg child (which could
> even be the very same script switching behaviors based on an environment
> variable).
>
> 'Simply separate' sounds like 'miracle occurs here'. I don't see how
> you can do such a thing for challenge-response programs. Sure, it's
> easy for your own programs, but I don't see how you can do it for
> programs for which you cannot predict the precise prompt.

Please read the previous message (above) again. The 'miracle' is
explained there. In yet another words:

#! /bin/sh
xmit=`interactive_part`
echo "$xmit" | nohup daemon_part & exit 0

I hope it is clear now that 'interactive_part' has full access to
/dev/tty and can hence be arbitrarily unpredictable.

-Alex

Akos Polster

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to

this "daemon" will not fit the model of challenge/response
apps where the response depends not just on the challenge
but on time as well. The token card I'm using to connect
to my provider generates different tokens as the time goes

- Akos.

P.S. My true apologies. I acknowledge that we are really far
from the subject of the original posting.

Alexandre Ferrieux

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to
Akos Polster wrote:

>
> Alexandre Ferrieux wrote:
> >
> > #! /bin/sh
> > xmit=`interactive_part`
> > echo "$xmit" | nohup daemon_part & exit 0
> >
> > I hope it is clear now that 'interactive_part' has full access to
> > /dev/tty and can hence be arbitrarily unpredictable.
>
> this "daemon" will not fit the model of challenge/response
> apps where the response depends not just on the challenge
> but on time as well.

Why ???
'interactive_part' can be absolutely *anything* !!!
What does this challenge/response have to do with the idea of forking
something into the background later ?

-Alex

Mark Diekhans

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to
tpoi...@nyx10.nyx.net (Tom Poindexter) writes:

> To TclX guys Mark/Karl: if either of you are following this thread, how about
> adding 'id process session set' to call setsid() on systems that support it?
> I'll be glad to send a patch if you dont' have time.

Time is very limited; send a patch and we shall integrate it!

Many thanks,
Mark

Akos Polster

unread,
Jan 14, 1999, 3:00:00 AM1/14/99
to
Alexandre Ferrieux wrote:
>
> Akos Polster wrote:
> >
> > [..snip..]

> >
> > this "daemon" will not fit the model of challenge/response
> > apps where the response depends not just on the challenge
> > but on time as well.
>
> Why ???
> 'interactive_part' can be absolutely *anything* !!!
> What does this challenge/response have to do with the idea of forking
> something into the background later ?
>
> -Alex

OK I've just realized that my scenario has nothing to do
with Don's original criteria:

> Here's a simple scenario for which nohup& is insufficient:
>
> User wants to start a process in the background. Process prompts
> for password but does no further interaction.

- Akos.

Don Libes

unread,
Jan 14, 1999, 3:00:00 AM1/14/99
to
In article <369C5B...@cnet.francetelecom.fr> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> writes:
Don Libes wrote:
>
> > How do you handle a variable prompt from the program - such as
> > challenge-response?
>
> Again, 'Simply separate the interactive and background parts'.
> The interactive part is a one-liner in my example, but could well be
> more complex, including a loop of natural language queries (why not a
> Turing test ?). When all parameters have been gathered, pack them in a
> string, and pass it with the [echo] trick to the bg child (which could
> even be the very same script switching behaviors based on an environment
> variable).
>
> 'Simply separate' sounds like 'miracle occurs here'. I don't see how
> you can do such a thing for challenge-response programs. Sure, it's
> easy for your own programs, but I don't see how you can do it for
> programs for which you cannot predict the precise prompt.

Please read the previous message (above) again. The 'miracle' is
explained there. In yet another words:

#! /bin/sh


xmit=`interactive_part`
echo "$xmit" | nohup daemon_part & exit 0

I hope it is clear now that 'interactive_part' has full access to
/dev/tty and can hence be arbitrarily unpredictable.

That wasn't my question. My question was how you separate a program
(like say, telnet) into an interactive and non-interactive part?

Don

Alexandre Ferrieux

unread,
Jan 15, 1999, 3:00:00 AM1/15/99
to

Hmmm ! Please admit it wasn't obvious: do you realize how much you
slanted the original point of view ?
Of course it makes sense for the author of Expect to be interested in
such matters. But the original poster only asked how to fork/setsid in
Tcl, so his question was on the *design* side. Clearly, splitting this
way an existing blackbox is entirely another matter, admittedly a
difficult one.

Okay now let's do the exercise: (Off the top of my head...) I believe I
would use ptys (as Expect does of course) to remote-control the child
(say telnet), pass data back and forth during the interactive part, then
fork/setsid with the master pty still open, and then do the rest from
the background. I don't claim this is optimal; you're the expert !

-Alex

Don Libes

unread,
Jan 17, 1999, 3:00:00 AM1/17/99
to

Of course it wasn't obvious - what's the point of posting things that
are obvious?

slanted the original point of view ?

If you look at the usual system daemons, you'll find quite a few that
are not started by nohup& - and for very good reasons. I really
thought the example I offered was a simple enough one.

Of course it makes sense for the author of Expect to be interested in
such matters. But the original poster only asked how to fork/setsid in
Tcl, so his question was on the *design* side. Clearly, splitting this
way an existing blackbox is entirely another matter, admittedly a
difficult one.

Okay now let's do the exercise: (Off the top of my head...) I believe I
would use ptys (as Expect does of course) to remote-control the child
(say telnet), pass data back and forth during the interactive part, then
fork/setsid with the master pty still open, and then do the rest from
the background. I don't claim this is optimal; you're the expert !

If you do an actual implementation based on this idea, send it to me
and I'll put it in the public archive of Expect examples.

Don

Alexandre Ferrieux

unread,
Jan 18, 1999, 3:00:00 AM1/18/99
to

No. The *interpretation* of your question was not obvious.
I should have used the word 'cryptic', it'd have been *clearer* :^)

> If you look at the usual system daemons, you'll find quite a few that
> are not started by nohup& - and for very good reasons. I really
> thought the example I offered was a simple enough one.

From which you infer that daemons having an interactive part are the
general case. Interesting. Should be better known !

> Okay now let's do the exercise: (Off the top of my head...) I believe I
> would use ptys (as Expect does of course) to remote-control the child
> (say telnet), pass data back and forth during the interactive part, then
> fork/setsid with the master pty still open, and then do the rest from
> the background. I don't claim this is optimal; you're the expert !
>
> If you do an actual implementation based on this idea, send it to me
> and I'll put it in the public archive of Expect examples.

D'you mean you don't already have one ? You must be kidding - sorry I'm
really bad at deciphering the tone of some posts. If not, how is it
possible that even Expect doesn't solve nicely that pet problem of yours
?

-Alex

Don Libes

unread,
Jan 18, 1999, 3:00:00 AM1/18/99
to

Sorry - I didn't mean to imply that. My example was definitely not
run-of-the-mill for system daemons. (Common for Expect-based user
daemons though.)

> Okay now let's do the exercise: (Off the top of my head...) I believe I
> would use ptys (as Expect does of course) to remote-control the child
> (say telnet), pass data back and forth during the interactive part, then
> fork/setsid with the master pty still open, and then do the rest from
> the background. I don't claim this is optimal; you're the expert !
>
> If you do an actual implementation based on this idea, send it to me
> and I'll put it in the public archive of Expect examples.

D'you mean you don't already have one ? You must be kidding - sorry I'm

I meant that I don't already have one that works the way you described.

really bad at deciphering the tone of some posts. If not, how is it
possible that even Expect doesn't solve nicely that pet problem of yours
?

Expect provides the fork and disconnect commands for this purpose.

-Alex

0 new messages