You can always try the obvious things like ^C, ^D (eof), Escape etc., but if all fails I usually end up suspending the command with ^Z (Control-Z) which puts me back into the shell.

I then do a ps command and note the PID (process id) of the command and then issue a kill thePID (kill -9 thePID if the former didn't work) command to terminate the application.

Note that this is not a tidy (no pun intended) way to terminate the application/command and you run the risk of perhaps no saving some data etc.

An example (I'd have used tidy but I don't have it installed):

$ gnuplot

    G N U P L O T
    Version 4.2 patchlevel 6 
     ....
    Send bug reports and suggestions to <http://sourceforge.net/projects/gnuplot>

Terminal type set to 'wxt'
gnuplot> 
gnuplot>               #####  typed ^Z here
[1]+  Stopped                 gnuplot
$ ps
  PID TTY          TIME CMD
 1681 pts/1    00:00:00 tcsh
 1690 pts/1    00:00:00 bash
 1708 pts/1    00:00:00 gnuplot
 1709 pts/1    00:00:00 ps


$ kill 1708            ###### didn't kill the command as ps shows

$ ps
  PID TTY          TIME CMD
 1681 pts/1    00:00:00 tcsh
 1690 pts/1    00:00:00 bash
 1708 pts/1    00:00:00 gnuplot
 1710 pts/1    00:00:00 ps
$ kill -9 1708           ### -9 did the trick
$ 
[1]+  Killed                  gnuplot

$ ps
  PID TTY          TIME CMD
 1681 pts/1    00:00:00 tcsh
 1690 pts/1    00:00:00 bash
 1711 pts/1    00:00:00 ps
Answer from Levon on Stack Exchange
Discussions

bash - How to cancel a command inside a script without exiting the script itself? - Unix & Linux Stack Exchange
When running a script with some lines not too important for the script to finish, how do I cancel a specific command without killing the entire script? Normally I would invoke Ctrl+c, but when I d... More on unix.stackexchange.com
🌐 unix.stackexchange.com
April 23, 2020
How to properly stop execution?
I Ctrl-C‘d while the rsync part was running, it stopped the rsync and happily continued with the rm. This is fundamentally a bug in Rsync. When you hit Ctrl+C, a SIGINT signal is sent to all processes in the foreground process group. This is a non-interactive shell, so both the shell as well as all the Rsync processes are in the same process group. All of them receive this SIGINT signal. The normal action for SIGINT is to terminate the process. I want to make it utterly clear that this is distinct from the process exiting. Processes can exit with an exit status, or they can terminate due to a signal. Terminating due to a signal is not exiting. Getting back to what happens when you hit Ctrl+C, let's first consider your shell. It has set up a handler for this signal. All it does is record that a SIGINT was received, but it does not immediately do anything about it. It has to wait for Rsync to exit first to know what to do. What does Rsync do with this signal? It also handles this signal. The problem is that Rsync simply exits after handling it. The correct thing for it to do would be whatever cleanups it needed to do, deregister the signal handler, then re-raise the signal against itself. But it doesn't do that. It simply does its cleanups and exits. So Bash sees that the program exited — not terminated! — and under this scenario it simply goes on to the next command (the rm in your script). This makes perfect sense. Imagine if instead of running Rsync you had instead started an interactive shell. You don't want any use of Ctrl+C in that shell to affect the operation of the script that ran the shell. If Rsync did the right thing, it would re-raise the SIGINT against itself so that it terminates due to this signal, rather than exits. Your shell would go "aha, I've received a SIGINT, and the program I ran terminated due to a SIGINT... that tells me I should also re-raise the signal against myself and terminate due to that signal". That would prevent the rm from executing. (If you want to dig into this stuff even more, this document is very useful. Bash implements what this document calls the "wait and cooperative exit" model of SIGINT handling. This is summarised in the bottom row of the table at the bottom of the page. The second-last entry in this row explains exactly what you're seeing: "If the child did a normal exit (even if it received SIGINT, but catches it), the script will continue.") How would I have prevented that? Ideally, Rsync would be fixed. But failing that, you're going to have to assume that Rsync always exits, never terminates. In this case, yes, handling its exit status in some way is the correct approach. It could be as simple as: rsync something || exit $? rm -r something One would assume that Rsync would exit with a non-zero exit status after handling the signal, so this will ensure that the rm is not called in this situation. Alternatively, you could work around the issue by installing your own trap for the signal in the script. This trap will be executed when Rsync exits or terminates, if SIGINT had been received while Rsync was running. More on reddit.com
🌐 r/bash
8
3
October 19, 2019
How can I cancel the rest of a list of commands in Bash? - Unix & Linux Stack Exchange
In Bash, occasionally I will type in a list of commands and hit Enter, and only later realize that there is a mistake with some command near the end of the list. I know that if I press Ctrl+C it w... More on unix.stackexchange.com
🌐 unix.stackexchange.com
April 2, 2018
bash - How to cancel edit-and-execute-command? - Unix & Linux Stack Exchange
Is there a way to not execute a command, once I have pressed Ctrl+X Ctrl+E? (edit-and-execute-command) Ideally like in git: If I save the file (like :wq in vim), it gets executed, but if I close th... More on unix.stackexchange.com
🌐 unix.stackexchange.com
🌐
Quora
quora.com › How-do-you-cancel-a-command-in-Linux
How to cancel a command in Linux - Quora
Answer (1 of 2): The keyboard shortcut "Ctrl + C" can be used to cancel a command in Linux. This causes the command to receive the interrupt signal and terminate right away. Alternatively, you can use the "kill" command followed by the process ID of the command to halt a background-running comma...
🌐
W3Schools
w3schools.com › bash › bash_kill.php
Bash kill Command - Terminate Processes
Bash Syntax Bash Script Bash Variables Bash Data Types Bash Operators Bash If...Else Bash Loops Bash Functions Bash Arrays Bash Schedule (cron) ... The kill command is used to terminate processes in a Unix-like operating system.
🌐
Reddit
reddit.com › r/bash › how to properly stop execution?
r/bash on Reddit: How to properly stop execution?
October 19, 2019 -

The other day I ran a trivial script that just does

rsync something
rm -r something

I Ctrl-C‘d while the rsync part was running, it stopped the rsync and happily continued with the rm.

How would I have prevented that? (I think &amp;&amp;‘ing the commands together would do the trick since the second would only run if the first succeeded but what do I do if there‘s like 30 commands in the script and I want to really really exit at once?)

Top answer
1 of 5
10
I Ctrl-C‘d while the rsync part was running, it stopped the rsync and happily continued with the rm. This is fundamentally a bug in Rsync. When you hit Ctrl+C, a SIGINT signal is sent to all processes in the foreground process group. This is a non-interactive shell, so both the shell as well as all the Rsync processes are in the same process group. All of them receive this SIGINT signal. The normal action for SIGINT is to terminate the process. I want to make it utterly clear that this is distinct from the process exiting. Processes can exit with an exit status, or they can terminate due to a signal. Terminating due to a signal is not exiting. Getting back to what happens when you hit Ctrl+C, let's first consider your shell. It has set up a handler for this signal. All it does is record that a SIGINT was received, but it does not immediately do anything about it. It has to wait for Rsync to exit first to know what to do. What does Rsync do with this signal? It also handles this signal. The problem is that Rsync simply exits after handling it. The correct thing for it to do would be whatever cleanups it needed to do, deregister the signal handler, then re-raise the signal against itself. But it doesn't do that. It simply does its cleanups and exits. So Bash sees that the program exited — not terminated! — and under this scenario it simply goes on to the next command (the rm in your script). This makes perfect sense. Imagine if instead of running Rsync you had instead started an interactive shell. You don't want any use of Ctrl+C in that shell to affect the operation of the script that ran the shell. If Rsync did the right thing, it would re-raise the SIGINT against itself so that it terminates due to this signal, rather than exits. Your shell would go "aha, I've received a SIGINT, and the program I ran terminated due to a SIGINT... that tells me I should also re-raise the signal against myself and terminate due to that signal". That would prevent the rm from executing. (If you want to dig into this stuff even more, this document is very useful. Bash implements what this document calls the "wait and cooperative exit" model of SIGINT handling. This is summarised in the bottom row of the table at the bottom of the page. The second-last entry in this row explains exactly what you're seeing: "If the child did a normal exit (even if it received SIGINT, but catches it), the script will continue.") How would I have prevented that? Ideally, Rsync would be fixed. But failing that, you're going to have to assume that Rsync always exits, never terminates. In this case, yes, handling its exit status in some way is the correct approach. It could be as simple as: rsync something || exit $? rm -r something One would assume that Rsync would exit with a non-zero exit status after handling the signal, so this will ensure that the rm is not called in this situation. Alternatively, you could work around the issue by installing your own trap for the signal in the script. This trap will be executed when Rsync exits or terminates, if SIGINT had been received while Rsync was running.
2 of 5
3
The safest way to kill a script run interactively is: Ctrl-Z to suspend it immediately, then kill %% to send SIGTERM to the job (i.e. the script and all its currently-running processes) you just suspended For more details, read the JOB CONTROL section of the bash man page. Also: I think &&ing the commands together would do the trick since the second would only run if the first succeeded That is in fact what you should have done, regardless of whether you felt the need to stop it prematurely. rsync can fail for all sorts of reasons (network failure, disk full, etc.), so your script logic should never assume everything it runs will always succeed.
Find elsewhere
Top answer
1 of 4
21

You can use the timeout command to run a command with a time limit. Its basic syntax is:

timeout DURATION COMMAND

where DURATION is a floating point number with the suffix s for seconds, m for minutes, h for hours or d for days and COMMAND is the command you wish to run.

In your case, you can use:

timeout 10s vlc -vvv http://10.0.0.113:8000/stream.mjpg --sout="#std{access=file,mux=ogg,dst=/home/whsrobotics/vlc_project/first_try.mp4}"

to run your command for 10 seconds and then kill it.

2 of 4
8

Add & after the second line to put VLC in the background like so:

#!/usr/bin/bash
vlc -vvv http://10.0.0.113:8000/stream.mjpg --sout="#std{access=file,mux=ogg,dst=/home/whsrobotics/vlc_project/first_try.mp4}" &
sleep 10
killall vlc

and it will work.


Explaination:

The shell/terminal will execute commands in the order they are listed in the script and will move to the next command only if the command before it finishes executing.

Which is not the case in your VLC command. As long as VLC is running, the shell/terminal will consider it still executing and will not move to the command after it but will rather wait for it to finish executing ( ie. in this case closing the VLC window/instance ).

A workaround this is to send VLC to the background and free the shell/terminal prompt for the next command in the script. Which can be done by adding & after the command.


Notice:

  • Remove verbosity option -vvv to avoid the script not exiting cleanly and completely.

  • If, however, you have to use the verbosity option -vvv add nohup before the second line as well like so:

#!/usr/bin/bash
nohup vlc -vvv http://10.0.0.113:8000/stream.mjpg --sout="#std{access=file,mux=ogg,dst=/home/whsrobotics/vlc_project/first_try.mp4}" &
sleep 10
killall vlc

This will append output to a file called nohup.out in the current working directory if possible or to ~/nohup.out otherwise and will allow the script to terminate cleanly and completely.

See man nohup for information.

Best of luck

🌐
Quora
quora.com › How-can-I-stop-a-running-Bash-script-or-command
How to stop a running Bash script or command - Quora
Answer (1 of 4): [Ctrl]-C normally causes your system (specifically the terminal driver in the kernel) to dispatch a "INT"-erupt signal to the currently attached/foreground process to which that terminal is connected. (Yes, these are almost always psuedo-terminals connected through your terminal...
🌐
TutorialsPoint
tutorialspoint.com › unix_commands › cancel.htm
cancel Command in Linux
The cancel command in Linux serves a single, specific purpose: to manage print jobs. It allows you to stop printing tasks that have been sent to a printer, either locally or on a print server.
Top answer
1 of 3
48

You have few options. One is to stop the script (CtrlZ), get the PID of the script and send SIGKILL to the process group.

When a command is executed in a shell, the process it starts and all its children are part of the same process group (in this case, the foreground process group). To send a signal to all processes in this group, you send it to the process leader. For the kill command, process leader is denoted thus:

kill -PID

Where PID is the process ID of the script.

Example:

Consider a script test.sh which launches some processes. Say you ran it in a shell:

$ ./test.sh

In another terminal,

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

In this case, to send a signal to process group created by test.sh, you'd do:

kill -INT -17802

-INT is used to send SIGINT, and so this command is the equivalent of pressing CtrlC on the terminal. To send SIGKILL:

kill -KILL -17802

You only need to stop the script if you can't open another terminal. If you can, use pgrep to find the PID.

One of the commands that the script launches may be trapping SIGINT, which is probably why CtrlC is ineffective. However, SIGKILL can't be trapped, and it is usually a last-resort option. You might want to try SIGTERM (-TERM) before going for the kill. Neither SIGKILL or SIGTERM can be set up as a keyboard shortcut the way SIGINT is.

All this is moot if your script doesn't contain a shebang line. From this SO answer:

Usually the parent shell guesses that the script is written for the the same shell (minimal Bourne-like shells run the script with /bin/sh, bash runs it as a bash subprocess) ...

Because of this, when the script is executed, you won't find a process named after script (or a process with the script's name in the command line) and pgrep will fail.

Always use a shebang line.

2 of 3
6

If you know the processes that are associated with the script you can find their PID using

 ps -A

and then use the PID number to kill the corresponding processes using

 kill -9 PID_Number
🌐
Bash Commands
bashcommands.com › make-bash-script-exit-on-cancel
Make Bash Script Exit on Cancel: A Simple Guide
August 7, 2024 - #!/bin/bash trap 'echo "Script canceled."; exit' SIGINT # Your script logic here while true; do echo "Running... Press Ctrl+C to cancel." sleep 1 done · In Bash, exit codes are key indicators of whether a script or command executed successfully or encountered an error.
🌐
nixCraft
cyberciti.biz › nixcraft › howto › bash shell › how to stop/interrupt cp or mv linux or unix command
How to stop/Interrupt cp or mv Linux or Unix command - nixCraft
August 16, 2017 - A user can stop or interrupt any command such as cp, mv and others by pressing CTRL–c (press and hold ctrl key followed by c) during the execution of a command or bash/perl/python script.
🌐
Reddit
reddit.com › r/bash › is it possible to stop a bash a bash script during execution and then return back to where you left off the next time you run the script
r/bash on Reddit: Is it possible to stop a bash a bash script during execution and then return back to where you left off the next time you run the script
August 31, 2022 -

Hopefully the title makes sense, for context let's say this is the situation:

  • I'm running a bash script that runs random commands one by one and in order to proceed to each next command the user has to press the spacebar. there are about 80 items

  • Let's say the user presses CTRL+C to stop the script from executing halfway through those 80 items

Is there a way to return back to where they were in script execution when they cancelled the script? Or do they have to re-run the script and then start at the very beginning again?

🌐
iO Flood
ioflood.com › blog › bash-exit-script
How to Exit Bash Scripts Effectively: Linux Shell Guide
December 1, 2023 - This command allows you to terminate a script at any point and optionally return a status. ... #!/bin/bash # This is a simple bash script echo 'Hello, World!' # Exit the script exit # Output: # 'Hello, World!'
🌐
Quora
quora.com › How-do-you-cancel-a-terminal-command
How to cancel a terminal command - Quora
Answer (1 of 2): If you mean Linux, you can find the process by using the ps command, you could just kill it For example your application is pluma ps ax|grep pluma 473269 pts/12 Sl+ 6:46 pluma abc kill 473269 if it doesn’t work, you could use kill -9 473269 If you want to pass just the name...
🌐
iO Flood
ioflood.com › blog › bash-exit
Bash Exit Command Explained: Script Terminating Tutorial
November 26, 2023 - If not provided, the exit command will return the status of the last command executed. ... #!/bin/bash echo 'Starting the script' exit 0 echo 'This will not be printed' # Output: # 'Starting the script'