Re: /etc/init.d/opendkim fails to start opendkim when run over ssh with a pseudo-tty

From: Scott Kitterman <ietf-dkim_at_kitterman.com>
Date: Sat, 16 Apr 2011 12:28:44 -0400

On Saturday, April 16, 2011 12:07:19 PM Steve Jenkins wrote:
> On Fri, Apr 15, 2011 at 10:02 AM, Sam Umbach <sumbach_at_gmail.com> wrote:
>
> Hi, Sam.
>
> > I've run into an issue with restarting the opendkim milter daemon over
> > ssh. I saw the issue on Ubuntu 10.10 Maverick and have already
> > reported it to the package maintainers
> > (https://bugs.launchpad.net/ubuntu/+source/opendkim/+bug/761967). I
> > am not sure if this issue is Ubuntu-specific.
> >
> > Without a pty, opendkim start and restart properly launch the opendkim
> > milter daemon:
> > $ ssh -T ubuntu_at_192.168.2.117 sudo /etc/init.d/opendkim restart
> > Restarting OpenDKIM: opendkim.
> >
> > But if I force pty allocation (as I do in my Capistrano deployments),
> > the opendkim daemon is NOT started:
> > $ ssh -tt ubuntu_at_192.168.2.117 sudo /etc/init.d/opendkim restart
> > Restarting OpenDKIM: opendkim.
> > Connection to 192.168.2.117 closed.
> >
> > As a workaround, I am able to disable pty allocation in my capistrano
> > script: sudo "/etc/init.d/opendkim restart", :pty => false
> >
> > * Can anyone confirm this issue on another distro?
>
> Here's what I get issuing a restart on CentOS and Fedora 12 if
> OpenDKIM is not started on the remote host:
>
> [stevej_at_host1 ~]$ ssh -tt stevej_at_host2 sudo /etc/init.d/opendkim restart
> stevej_at_host2's password:
> Stopping OpenDKIM Milter: [FAILED]
> Starting OpenDKIM Milter: [ OK ]
> Connection to host2 closed.
>
> > * How does /etc/init.d/opendkim daemonize the opendkim milter?
>
> Assuming you're using v1.3 of the RedHat init script in the OpenDKIM
> contrib directory, line 30 imports /etc/rc.d/init.d/functions. Here's
> the daemon function from that file on a CentOS 5.5 system:
>
> daemon() {
> # Test syntax.
> local gotbase= force= nicelevel corelimit
> local pid base= user= nice= bg= pid_file=
> nicelevel=0
> while [ "$1" != "${1##[-+]}" ]; do
> case $1 in
> '') echo $"$0: Usage: daemon [+/-nicelevel] {program}"
> return 1;;
> --check)
> base=$2
> gotbase="yes"
> shift 2
> ;;
> --check=?*)
> base=${1#--check=}
> gotbase="yes"
> shift
> ;;
> --user)
> user=$2
> shift 2
> ;;
> --user=?*)
> user=${1#--user=}
> shift
> ;;
> --pidfile)
> pid_file=$2
> shift 2
> ;;
> --pidfile=?*)
> pid_file=${1#--pidfile=}
> shift
> ;;
> --force)
> force="force"
> shift
> ;;
> [-+][0-9]*)
> nice="nice -n $1"
> shift
> ;;
> *) echo $"$0: Usage: daemon [+/-nicelevel] {program}"
> return 1;;
> esac
> done
>
> # Save basename.
> [ -z "$gotbase" ] && base=${1##*/}
>
> # See if it's already running. Look *only* at the pid file.
> __pids_var_run "$base" "$pid_file"
>
> [ -n "$pid" -a -z "$force" ] && return
>
> # make sure it doesn't core dump anywhere unless requested
> corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}"
>
> # if they set NICELEVEL in /etc/sysconfig/foo, honor it
> [ -n "${NICELEVEL:-}" ] && nice="nice -n $NICELEVEL"
>
> # Echo daemon
> [ "${BOOTUP:-}" = "verbose" -a -z "${LSB:-}" ] && echo -n " $base"
>
> # And start it up.
> if [ -z "$user" ]; then
> $nice /bin/bash -c "$corelimit >/dev/null 2>&1 ; $*"
> else
> $nice runuser -s /bin/bash - $user -c "$corelimit
>
> >/dev/null 2>&1 ; $*"
>
> fi
> [ "$?" -eq 0 ] && success $"$base startup" || failure $"$base
> startup" }
>
> I have Ubuntu on my laptop, but won't be able to hack on it until
> later tonight. I'm not too versed in the differences between
> Ubuntu/Deb and CentOS/RedHat, so I don't know enough about it to
> intelligently answer your question - but I'm happy to work with you to
> see if we can figure it out. When we do, I'm sure Murray can add a
> /debian dir to the /contrib/init dir and we can put a version of the
> script in there.
>
> Best,
>
> SteveJ

I generally maintain the package in Ubuntu and will be glad to update it in
the Ubuntu archive when there's a fix. I'll also make sure the Debian
maintainer is aware of it. In Debian (and Ubuntu) packaging we generally
prefer that upstreams not ship /debian directories. They tend to be poorly
maintained and get in the package maintainers way, so I'd prefer it not be
added.

The equivalent function in Debian/Ubuntu is in start-stop-daemon which is part
of the dpkg package. It's in C, here's ~equivalent fragment (from
utils/start-stop-daemon.c):

daemonize(void)
{
        pid_t pid;

        if (quietmode < 0)
                printf("Detaching to start %s...", startas);

        pid = fork();
        if (pid < 0)
                fatal("unable to do first fork");
        else if (pid) /* Parent. */
                _exit(0);

        /* Create a new session. */
#ifdef HAVE_SETSID
        setsid();
#else
        setpgid(0, 0);
        detach_controlling_tty();
#endif

        pid = fork();
        if (pid < 0)
                fatal("unable to do second fork");
        else if (pid) /* Parent. */
                _exit(0);

        if (quietmode < 0)
                printf("done.\n");
}

It's in Git, so if you want to look at the whole file it's at
http://git.debian.org/?p=dpkg/dpkg.git;a=blob_plain;f=utils/start-stop-
daemon.c;hb=HEAD

Scott K
Received on Sat Apr 16 2011 - 16:29:06 PST

This archive was generated by hypermail 2.3.0 : Mon Oct 29 2012 - 23:20:17 PST