The problem:
With lsof -i :3000 -t
, you will look for any processes connected to a port 3000, which may be on the remote side.
In the cases where you use your script, the browser seems to have a connetction to the rails server on port 3000. The difference is in the timing between using the browser and using kill
.
That means the browser is listed in the output of lsof
too, and killed.
You should better kill processes that look like your rails server, not anything that is using a port 3000, locally or elsewhere.
The general solution:
pkill
is the right tool for the job.
For trying what is matched, use pgrep
, which matches the same way:
If the command line of the server, as shown in ps, starts with a command name that identifies your server instance, you can use pkill servercommand
.
If you need to match a part of the command line arguments, add -f
, like pkill -f serverargument
.
The processes that are killed by pkill
will just be listed by pgrep
- so use that to try what will be killed. Add the option -a
to pgrep
to list the command line, instead of the pid only.
Examples for pgrep / pkill:
As an example for using -f
: According to ps
, these two instances of xbindkeys
are running:
$ ps aux|grep '[x]bindkeys'
26719 ? S 0:00 xbindkeys -f /tmp/xbindkeysrc-tmp
32046 ? S 0:00 xbindkeys -f /home/auser/.xbindkeysrc
Now I can find both instances with:
$ pgrep xbindkeys
26719
32046
Or showing the commands:
$ pgrep -a xbindkeys
26719 xbindkeys -f /tmp/xbindkeysrc-tmp
32046 xbindkeys -f /home/auser/.xbindkeysrc
Or match one of the instances by the command line arguments:
$ pgrep -f '/home/auser/.xbindkeysrc'
32046
Without -f
, none of the processes are matched:
$ pgrep '/home/auser/.xbindkeysrc'
Finally, sending the process a signal, like with kill
:
$ pkill -f '/home/auser/.xbindkeysrc'
Alternative solution based on original approach:
The solution with pkill
is much more general, but to follow your original approach, the lsof
command can be made more strict to match
"any local server listening on the port",
instead of
"any program using the local port in any way, or using a remote port of that number in any way".
The option -sTCP:LISTEN
restricts the list to ports listening on, and, as only local ports can be listened on, also to local ports only.
It could be used as a if
test like this:
if lsof -i :3000 -sTCP:LISTEN -t >/dev/null ; then
echo running
else
echo not running
fi
Side note on using SIGKILL, as in kill -9:
The KILL signal can be used with pkill
just the same way as with kill
:
$ pkill -9 -f '/home/auser/.xbindkeysrc'
But in most general cases, that has no advantage above the default signal -15
, and in some cases, it breaks things. So it's not a good idea to make it a habit.
Take a look at When should I not kill -9 a process? to understand why you do not want to use -9
by default.
kill -9
? There are other signals you can try if the default doesn't work. – chepner Aug 12 '14 at 12:10