Skip to content
nugget edited this page Sep 13, 2010 · 5 revisions

tcllauncher

tcllauncher is a way to have Tcl programs run out of /usr/local/bin, or wherever. (It also provides tools for Tcl-based daemons to manage themselves.)

Now you might think, why bother? I’ll just put my script in there and do a #! thing to invoke Tcl.

Well, OK, but this has certain problems:

  • Everything will show in ps as tclsh
  • Everything will show in top as tclsh
  • If there are any files you want to pull in that aren’t in a package, you have to invent your own place to install and locate them.

You’d like to be able to have stuff show up as its script name.

You could just copy or even link tclsh to the name of your program. Say, for instance, trackserver.

But then you have to invoke trackserver with arguments and do stuff to prep it, like:


    cd ...somewhere...
    /usr/local/bin/trackserver main.tcl

That’s the original purpose for tcllauncher, just to make that reasonable.


    cp /usr/local/bin/tcllauncher /usr/local/bin/trackserver
    trackserver

How does it find its files? It cd’s to the corresponding lib directory and a directory underneath that of the same name as the application, and sources main.tcl with tcl_interactive set to 0.

run

trackserver

what happens

/usr/local/bin/trackserver, a copy of /usr/local/bin/tcllauncher, sources in /usr/local/lib/trackserver/main.tcl.

Also, a global variable called launchdir is set containing the “launch directory.” In the above example, /usr/local/lib/trackserver.

what directory

Tcllauncher doesn’t change your directory behind your back, so wherever you are at when you run it, you’re still in that directory.

But a lot of times you want to go to your application directory, so you can just

cd $::launchdir

Then you can source in all of your various files and stuff like that.

process group

If you are going to fork off children, exec them, or whatever, you should
probably become your own process group so hopefully your children might
inherit your signals and Do The Right Thing.

package require Tclx id process group set

user and group management

If a program needs to be run as a certain use, it can invoke

::tcllauncher::require_user fred

This requires the program to either be run as fred or as root or something
like that, a user that has permissions to become fred.

If the program is running as user fred or can change the user id (suid) to
fred, it continues, else it aborts.

::tcllauncher::require_group does for groups what require_user does for
users.

Note that if you require user first then require group, the process may have
lost the privileges necessary to change groups after changing users. Either
require the group ID first or use ::tcllauncher::require_user_and_group
to do both.

pid file

Lots of apps write a file with the server’s process ID in it. Upon relaunch,
the program can come along and look in its own pid file to see if it’s already
alive or not, and also to potentially kill it.

Our pidfile support is a studied Tcl-based copy of BSD’s pidfile C library.

::tcllauncher::pidfile_open

Given an optional path to a directory and optional permissions, pidfile_open opens (or creates) a file specified by the path and locks it with TclX’s interface to the flock system call.

If the file cannot be locked, the PID of an already running daemon is returned.

Otherwise zero is returned and you’ve got the lock. You can now call pidfile_write to get your pid into the lock file.

This function does not write your process’ PID into the file, so it can be used before forking if needed.

::tcllauncher::pidfile_write

Writes your pid into the pid file previously opened by pidfile_open.

::tcllauncher::pidfile_close

Close a pidfile. It should be used after your daemon forks to start a child process.

::tcllauncher::pidfile_remove

Close and remove a pidfile.

example


    set pid [::tcllauncher::pidfile_open /var/run 0600]
    if {$pid > 0} {
	puts stderr "pid $pid already has the lock"
	exit 1
    }

    ::tcllauncher::daemonize

    ::tcllauncher::pidfile_write

    ...do work...

    ::tcllauncher::pidfile_remove
    exit

daemonize

Sometimes you want your program to spawn itself off into the background in
a way that when you logout it doesn’t kill the process, etc.

To daemonize a tcllauncher app,

::tcllauncher::daemonize

By default this forks off a child and exits the parent. In the child, it
changes the current directory to /, and redirects stdin, stdout and stderr
to/from /dev/null.

Optional arguments are -noclose, which prevents the closing and redirecting
of stdin, stdout and stderr, and -nochdir, which prevents the changing of
the working dir to /.

::tcllauncher::daemonize -nochdir

This is a rough copy of BSD 4.4’s daemon library routine.