0

I have a script that runs in the background. It opens an SSH connection to a server and tails a file indefinitely. When I put my mac to sleep, the SSH connection is closed. Here is the script in question:

#!/bin/sh

(ssh <user>@<ip> -o PermitLocalCommand=no  \
 ": > .irssi/fnotify ; tail -f .irssi/fnotify " | \
 while read heading message; do                   \
 growlnotify -s -t "${heading}" -m "${message}";  \
 done)&

At that point, I have to run ps aux | grep ssh, find the right process and kill it manually; It's tedious. So I have a couple of questions and potential answers:

  1. Is there a way to rename the process name of the script so that I can kill it by name everytime I run it again?
  2. Otherwise, is there a way to store the pid of the script when I execute it and then kill it when I run it again?

The first solution is impossible I believe, but it's worth asking.

For the second solution, I did some research I went somewhere but not far enough... Here is what I have:

I managed to get the pid of the script itself, not the one of the particular SSH connection. But from what I saw, the pid of the script is always <pid of ssh connection> - 1.

So I need to add 1 to the pid of the script, and I couldn't manage to do that. But anyway, is that a viable solution?

Otherwise, what are the alternative solutions please?

Robert Audi
  • 8,019
  • 9
  • 45
  • 67
  • I'm not sure, but using `-o ServerAliveInterval=0` may keep the connection alive as long as the client process isn't killed. – chepner Oct 17 '13 at 13:50

2 Answers2

1

You don't need to do any PID tracking, let the shell handle ssh disconnects in a loop.

#!/bin/sh
while true ; do
    ssh -o BatchMode=yes user@host '
        : > ~/.irssi/notify
        tail -f ~/.irssi/notify
    ' | while read -r title message ; do
        growlnotify -s -t "$title" -m "$message"
    done
    sleep 5  # retry timeout
done

Adjust user@host and retry timeout to taste, save in your path, chmod +x it, and run when convenient, like backgrounded from xinitrc/xsession or in a term if you want to watch output.

To guard against multiple instances you can prepend something like the following.

if [ -e /tmp/sshnotify.pid ] ; then
    read pid < /tmp/sshnotify.pid
    if kill -0 $pid > /dev/null 2>&1 ; then
        echo >&2 already running
        exit 1
    fi
fi
echo $$ > /tmp/sshnotify.pid
peth
  • 235
  • 1
  • 5
  • I have two issues with your solution: 1. I'm not comfortable with doing multiple SSH connection every X seconds. 2. I tried to add `echo $$` at the top of the script and it returned the wrong pid.. – Robert Audi Oct 17 '13 at 14:49
  • 1. It doesn't; there is no backgrounding. The script waits for `ssh` to terminate, which it will on lost connection, _then_ waits for X seconds before trying to reconnect with `ssh`, until the entire script is killed at system shutdown or manually with `kill $(cat /tmp/sshnotify.pid)` or `pkill `. 2. `$$` doesn't return the wrong pid, it returns the pid of the shell running this script. You don't need any other because if the script is killed, so are the subprocesses. `echo $$ > file` is so we have a file at a known location that contains the pid of an already running script. – peth Oct 17 '13 at 16:00
0

Since you're using zsh, you can set the name of the ssh process by setting the ARGV0 parameter for it. You'd do that by putting ARGV0=WhateverNameYouWant right before the ssh, but still inside of the parentheses.

The PID of the last process run in the background is available as $!, but since you don't have a simple command that you're backgrounding that will not be the PID of the ssh process. But, I suspect that might be what you were using to find the PID of the script.

You can do math in the shell by wrapping it inside $(( )), like $(($! + 1)). You can leave the $ off of some variable references inside those expressions, but that doesn't seem to work for $!. But, adding 1 to a PID would not be a reliable way to get the PID of a child process; it would only take a different process spawning a child at just the wrong time to throw that off.

qqx
  • 18,947
  • 4
  • 64
  • 68
  • So setting the name of the process is the best solution? What I had in mind is to export the name of the process in a variable and then check for that and kill the process if it's running. But how can I check if a named process is running? :S – Robert Audi Oct 17 '13 at 12:10