37

When I do tail -f filename, how to quit the mode without use Ctrl+c to kill the process?

What I want is a normal way to quit, like q in top.

I am just curious about the question, because I feel that killing the process is not a good way to quit something.

dr_
  • 29,602
Key Shang
  • 859
  • 25
    tail is not interactive; it does not take commands. – muru Aug 22 '17 at 07:13
  • @muru Hi, "tail is not interactive" means tail -f doesn't have normal quit way, the only way is using Ctrl+c? – Key Shang Aug 22 '17 at 07:22
  • In effect, yes. You can also kill it by doing kill <pid> or pkill tail, but all three do the same thing: send a signal to tail that kills it. – muru Aug 22 '17 at 07:23
  • You question is quiet confusing. Do you want to use the command in the script shell, so use --pid=PID with -f, terminate after process ID, PID dies found in the man. – dubis Aug 22 '17 at 07:24
  • @dubis Thanks for your advise, I am just curious about the question, because I feel kill process is not a good way to quit something. I am Linux newcomer, sorry for if I asked a stupid question. – Key Shang Aug 22 '17 at 07:34
  • @muru Get it. Thanks for your answer, I am just curious about the question, because I feel kill process is not a good way to quit something. I am Linux newcomer, sorry for if I asked a stupid question. – Key Shang Aug 22 '17 at 07:44
  • Usually, yes, because the process may leave behind a mess (say, temporary files, or locked databases). tail doesn't do much, so it's perfectly alright to kill it. – muru Aug 22 '17 at 07:49
  • 5
    There is also difference between killing process with SIGTERM (default) and SIGKILL. SIGTERM 'asks' process to stop, and this signal can be handled by program. On the other hand SIGKILL actually kills the process. See man signal for more – mrc02_kr Aug 22 '17 at 07:56
  • 11
    The premise of this question is faulty. That special character does not "kill" the process in the way that you are thinking. It sends the interrupt signal to it, not the kill or terminate signals. – JdeBP Aug 22 '17 at 08:02
  • @muru Thanks for your additional information, you could organize your comment in the answer, I will accept it :) – Key Shang Aug 22 '17 at 08:03
  • Minor detail, @mrc02_kr: Ctrl-C sends SIGINT (interrupt), not SIGTERM (terminate). But the practical effect (a 'request' for the process to stop) is the same either way. – Dave Sherohman Aug 22 '17 at 12:30
  • 7
    It's perfectly reasonably to interrupt tail or even kill it without worry. But if you want an alternative, consider most, which has an admittedly under-documented "follow" mode, initiated with Shift+F, and can be cleanly exited with Q. – Toby Speight Aug 22 '17 at 15:49
  • 6
    The problem here is your perception that "killing the process is not a good way to quit something" -- sending ^C to a process is one way of saying "I'm done with you and I'd like you to stop", it is the "default" way to exit from a terminal process in Linux. If you're choosing to exit from some long running process, the repercussions of your choice to stop it may leave a mess, but tail -f isn't that :) – Josh Aug 22 '17 at 21:34
  • 2
    There's always tail() { trap "stty intr '^c'" 2 0; stty intr q; command tail "$@"; } – Mark Plotnick Aug 22 '17 at 23:39

8 Answers8

55

As said in the comments, Ctrl-C does not kill the tail process, which is done by sending either a SIGTERM or SIGKILL signal (the infamous -9...); it merely sends a SIGINT which tells tail to end the forward mode and exit.

FYI, these's a better tool:

less +F filename

In less, you can press Ctrl-C to end forward mode and scroll through the file, then press F to go back to forward mode again.

Note that less +F is advocated by many as a better alternative to tail -f. For difference and caveats between the two tools, read this answer: Is `tail -f` more efficient than `less +F`?

dr_
  • 29,602
  • 7
    Off-topic. The OP did not ask to "end the forward mode and scroll through the file". Rather, the OP asked how to quit tail -f without using Ctrl+C – fpmurphy Aug 22 '17 at 10:08
  • 8
    @fpmurphy1 Given that the OP's question premise is incorrect (tail is not killed by CTRL-C and is not interactive) I believe my answer is more than appropriate. – dr_ Aug 22 '17 at 11:37
  • 14
    @fpmurphy1 If you take the OP literally yes it's off-topic, however I prefer educational answers that address misunderstandings and at the same time give an answer to what the OP was actually trying to achieve, i.e. the real question. – MarioDS Aug 22 '17 at 11:58
  • 15
    "Ctrl-C does not kill the tail process" - Yes it does. Or at least as much as kill <pid> does. For most programs, there's no real difference between Ctrl-C (=SIGINT), SIGTERM and, to some extent, SIGKILL. The default action for all three is to simply terminate the process, as if exit() had been called, with the exception that for SIGKILL, none of the user-mode code associated with exit() is called (so no atexit() cleanups etc). Ctrl-C and SIGTERM, in particular, are completely identical unless the program explicitly catches either and acts on it. GNU tail doesn't. – marcelm Aug 22 '17 at 12:02
  • 3
    "normal mode, where you can scroll up and down the file" - is that some new version of tail of which I was previously not aware? – Toby Speight Aug 22 '17 at 15:51
  • The signal sending function in Unix is called kill. Ctrl-C doesn't use it, but some sort of kernel internal equivalent. – Kaz Aug 22 '17 at 18:45
  • @TobySpeight You're right, my mistake. I corrected the post. – dr_ Aug 23 '17 at 06:58
  • 4
    @marcelm Terminating the process is not the same as exit() being called. exit() will run the atexit() handlers, and clean up open stdio files (most importantly flushing output buffers). A SIGINT handler could do this, but most programs don't bother; I don't know whether tail does. – Barmar Aug 23 '17 at 17:46
  • 1
    Note that less is not always a better tool than tail, they're different and have different advantages. E.G. with tail -f I can press enter a few times to "mark" where I was, or I can use tail -f | grep (or awk, cut, etc) – Josh Aug 23 '17 at 19:49
  • @Barmar I stand corrected! SIGTERM / SIGINT termination indeed doesn't do that. However, this brings SIGTERM / SIGINT and SIGKILL even closer than I argued before ;) – marcelm Aug 25 '17 at 10:05
19

What I want is a normal way to quit, like q in top.

That's ControlC :)

I am just curious about the question, because I feel that killing the process is not a good way to quit something.

^C (ControlC) sends a SIGINT to the process, which is defined as:

The SIGINT signal is sent to a process by its controlling terminal when a user wishes to interrupt the process

That's exactly what you want to do here, is interrupt tail. There's no other way to accomplish what you're trying to do ("nicely" quit tail) and while other answers provide a means to stop tail in other ways, they're no better.

Pressing ^C will attempt to interrupt a task in Linux -- this is perfectly normal, and it's only "not good" if that process is in the middle of something and you're not letting it finish, and then the only "not good" side effect is leftover things from that process. As an example, ^C in the middle of a make command leaves partially-compiled software, but that's fine: a further run of make will clean that up / resume where it left off.

Toby Speight
  • 8,678
Josh
  • 8,449
  • 2
    Actually, the make example is a reminder why we always write .DELETE_ON_ERROR: in our Makefiles - we want Make to remove partially-written intermediate files when it learns that one of its commands received a signal. – Toby Speight Aug 23 '17 at 07:26
  • Processes can trap SIGINT and do cleanup before exit as indicated in Toby's .DELETE_ON_ERROR: example. – Dennis Williamson Aug 23 '17 at 15:45
  • 1
    Yes, the ability to trap SIGINT is exactly why I said it's what @Arthur wants. There's no need to be "nice" to tail, you won't hurt it's feelings with a ^C :) – Josh Aug 23 '17 at 19:44
12

tail -f filename, how to quit the mode without use Ctrl c to kill the process

You can't do that. Perhaps you wanted to run tail -f somefile | less

The Ctrl c is interpreted by the tty subsystem (and by your shell) and sends a SIGINT signal (see signal(7) and pty(7)...). See tty demystified.

7

This would work and answers your question, but is not a particularly satisfactory solution.

timeout 15s tail -f /var/log/messages

This will run the command for 15 seconds and then kill it for you, without having to press ^C

Criggie
  • 1,781
  • 5
    Yeah, so would shutting down the computer tail is being run on. Still, you're not wrong I guess. – Aaron Aug 22 '17 at 13:00
  • 5
    How is terminating tail with SIGTERM better than terminating it with SIGINT? – Dmitry Grigoryev Aug 22 '17 at 14:53
  • 1
    @DmitryGrigoryev You're totally right - its not better. But this answer directly answers the OP's question, even though its not really a lot of use in reality. However I have used timeout to terminate things like ping, when using a Dell DRAC Java app that requires a menu selection to press Control and a second menu choice to release control (that was just irritating, a Dell c5220 blade ) – Criggie Aug 22 '17 at 20:08
0

Assuming you have a function

function prll(){
..... 
pkill -9 -x tail
}

Assuming you run tail along your function

tail -n 1 -f file | 
pv -l > /dev/null | 
prll file

echo !!done!!

Conclusion, the answer is:

pkill -9 -x tail
Edward
  • 2,509
-1

Answers differ based on context. To quit tail -f elegantly, you will need a trigger. Assume you are trying to monitor output of a task that will finish at some point in time - that can become your trigger.

task >& filename.log &
task_pid=$!
tail -f filename.log &
tail_pid=$!
while [ 1 ]
do
    # -0 is a special "poke" signal - "are you around?"
    kill -0 $task_pid
    if [ $? -eq 0 ]
    then
        # Original task is still alive.
        sleep 2
        continue
    fi
    kill -TERM $tail_pid
    break
done

I have used similar ideas in the past.

Enjoy.

-1

I think another good approach is using the old ps + kill in another session.

ps -fea | grep tail

The above command would identify any tail running by any user, and after finding the right PID, just run kill. For example:

kill 999999

Hope this can help someone as an alternative approach.

  • That does exactly what the OP wanted to avoid (»I feel that killing the process is not a good way«). Your answer is not only more complicated, it makes things worse by sending SIGTERM, while the simple ctrl-c would send a smooth SIGINT. – Philippos Jun 09 '22 at 07:08
-2

Issuing

echo tail -n 1 -f <filename>

works for me though I'm not 100% sure it terminates the tail process.

Paulo Tomé
  • 3,782
  • 2
    The command you show does not do anything other than output the strings tail, -n, 1, -f and the filename with spaces between them. – Kusalananda Jun 02 '22 at 16:28