Ctrl+c in a sub process is killing a nohup'ed process earlier in the script

15

3

I didn't know whether this belonged on SO (as it is a coding bug) but thought you guys would be more knowledgeable regarding the subtleties of the software used (so maybe even U&L could be considered).

Here's the minimal code script (see edits for full script, there's a reason I'm doing it this way);

#/bin/bash
nohup {SERVERCOMMAND} > currentOutput.log 2>&1 &

less +F currentOutput.log

What it tries to do is run a server in the background, which outputs to a log file.
Then I follow that log file using less +F. As you do, to exit this you must hit ctrl+c before you can hit Q.

What happens is, when I ctrl+c inside the less command (to stop tailing) it somehow kills the server started with nohup at the top! Nothing else is affected. I can shift+f to start tailing the log again (which gets no new info since the server is killed) and if I hit Q the rest of the script executes normally.

Do you know why this happens? How to avoid it/something else I should be using?


P.S.
The server program may be listening for a ^C, which may be the issue; is there something I can do to stop that? Like, when I just run {SERVERCOMMAND} on its own (in a blocking manner), I can hit ctrl+c, which doesn't immediately kill it; it prints Received ^C signal, shutting down (and then kills itself). This is what's happening when I ^C in less (A final Received ^C signal, shutting down is written to the log).


P.P.S
I've been trying a number of things (none worked);

  • trying to disconnect the stdin from the script by changing

    nohup {SERVERCOMMAND} > currentOutput.log 2>&1 &
    to
    nohup echo '' | {SERVERCOMMAND} > currentOutput.log 2>&1 &
    or
    nohup cat /dev/null/ | {SERVERCOMMAND} > currentOutput.log 2>&1 &
    
  • using stty intr ^G to replace the interrupt command, but then ctrl+g did exactly what ^C was doing anyway (so this may be an issue with my terminal emulator instead; konsole)

  • placing the nohup &/or the less line in parentheses (to make it a subshell)

  • running the script in xterm instead of konsole

Hashbrown

Posted 2014-01-30T02:50:56.820

Reputation: 1 720

3nohup prevents the process from receiving SIGHUP signal whereas CTRL+C sends SIGINT signal. That's why nohup doesn't have the effect you expected. – Piotr Dobrogost – 2015-01-27T10:06:12.603

Someone may have come across my issue; I think it is due to the handling within the database software, not on the shell. How would a program do this? How, then, might I stop it?

– Hashbrown – 2014-01-30T06:10:37.627

Answers

11

I was right in thinking that it was SIGINT being sent to all processes when ctrl+c, but I was silly in thinking that making another process would bring it outside the process group (see my attempts in the P.P.S.).

This is, not only the exact use case, but the correct solution.

Because of how my script was structured the answer there didn't fit verbatim, this is the script now;

#/bin/bash

setsid {SERVERCOMMAND} > currentOutput.log 2>&1 &
less +F currentOutput.log

The server continues to output to the log file after I ctrl+c in less.

Thanks for everyone's time.

Hashbrown

Posted 2014-01-30T02:50:56.820

Reputation: 1 720

0

Have you tried disown?

  disown -h %1

or whatever your job is; disown is a shell built-in, its man page states:

disown

disown [-ar] [-h] [jobspec ...]

Without options, each jobspec is removed from the table of active jobs. If the -h' option is given, the job is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. If jobspec is not present, and neither the-a' nor -r' option is supplied, the current job is used. If no jobspec is supplied, the-a' option means to remove or mark all jobs; the `-r' option without a jobspec argument restricts operation to running jobs.

EDIT

Funny thing, your construction works on my Arch Linux:

 $ cat testm
  #!/bin/sh

  nohup /home/mario/temp/waste & 

  less +F out.log

 $ cat waste
  #!/bin/sh

  while [ 1 ]; do
    find / -print 2>1 1> out.log
  done
  $ ./testm
   nohup: appending output to ‘nohup.out’
  $ ps ax | grep waste
    19090 pts/2    S      0:00 /bin/sh /home/mario/temp/waste
    19124 pts/2    S+     0:00 grep waste]
  $

Before the ps command, I had to scroll the out.log file, then Ctrl+C, then q.

MariusMatutiae

Posted 2014-01-30T02:50:56.820

Reputation: 41 321

yes, but I don't know how to apply it. I tried placing the nohup line in a function which disowns itself, but that should be the same as nohup. I don't think this is a SIGHUP issue, as when I remove the less line, the script concludes with the server still running – Hashbrown – 2014-01-30T04:36:50.967

@Hashbrown pls see my edit – MariusMatutiae – 2014-01-30T08:09:17.187

Yeah I did a test as well, with a simple bash script being called instead of {SERVER} executable. And nohup just worked fine. See my comment on the question. I think it is purposefully listening somehow. Since its a propriety (and not well known) server I can't even say what it is so someone can go "oh its doing X, you need to do Y" – Hashbrown – 2014-01-30T21:34:11.563