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 ExchangeYou 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
Try pressing Ctrl-D or Ctrl-C. If it fails, kill the process .
Trying with the tidy command you mentioned, Ctrl-D works.
Some things won't respond to Ctrl+C; in that case, you can also do Ctrl+Z which stops the process and then kill %1 - or even fg to go back to it. Read the section in man bash entitled "JOB CONTROL" for more information. It's very helpful. (If you're not familiar with man or the man pager, you can search using /. man bash then inside it /JOB CONTROLEnter will start searching, n will find the next match which is the right section.)
Ok, so this is the order:
1st try: Ctrl+c
2nd try: Ctrl+z
3rd: login to another console, find the process of the command within your first console that is not responding to both previously mentioned abort/sleep keystrokes with: ps aux
Then kill the process with: kill -9 <PROCESSID>
Of course there may be smarter parameters to the ps command or the possibility to grep , but this would complicate the explanation.
bash - How to cancel a command inside a script without exiting the script itself? - Unix & Linux Stack Exchange
How to properly stop execution?
How can I cancel the rest of a list of commands in Bash? - Unix & Linux Stack Exchange
bash - How to cancel edit-and-execute-command? - Unix & Linux Stack Exchange
The "problem" really is that you're sourcing and not executing the script. When you source a file, its contents will be executed in the current shell, instead of spawning a subshell. So everything, including exit, will affect the current shell.
Instead of using exit, you will want to use return.
Yes; you can use return instead of exit. Its main purpose is to return from a shell function, but if you use it within a source-d script, it returns from that script.
As §4.1 "Bourne Shell Builtins" of the Bash Reference Manual puts it:
return [n]Stop executing a shell function or sourced file and return the value n to its caller. If n is not supplied, the return value is the exit status of the last command executed. […]
[…]
The return status is non-zero if
returnis supplied a non-numeric argument or is used outside a function and not during the execution of a script by.orsource.
I think you are looking for traps:
trap terminate_foo SIGINT
terminate_foo() {
echo "foo terminated"
bar
}
foo() {
while :; do
echo foo
sleep 1
done
}
bar() {
while :; do
echo bar
sleep 1
done
}
foo
Output:
./foo
foo
foo
foo
^C foo terminated # here ctrl+c pressed
bar
bar
...
Function foo is executed until Ctrl+C is pressed, and then continues the execution, in this case the function bar.
#! /bin/bash
trap handle_sigint SIGINT
ignore_sigint='no'
handle_sigint () {
if [ 'yes' = "$ignore_sigint" ]; then
echo 'Caught SIGINT: Script continues...'
else
echo 'Caught SIGINT: Script aborts...'
exit 130 # 128+2; SIGINT is 2
fi
}
echo 'running short commands...'
sleep 1
sleep 1
ignore_sigint='yes'
echo 'running long commands...'
sleep 10
ignore_sigint='no'
echo 'End of script.'
There are a few keypresses that should help you here.
Ctrl+C should send the foreground process SIGINT, and that should terminate the process unless you trap the signal with something like trap INT ... in your shell code.
Ctrl+Z should send SIGSTOP, which would pause your process, again unless you trap your signals.
The mapping of key sequences jumps through some hoops, including terminal settings. What does stty -a say on your computer? Look in the output for intr, that's the keypress that should trigger SIGINT. If nothing is set, you need to set it, something like stty intr ^C
As others have said, you can kill the process from another window as well.
If Ctrl + C isn't working for you, you can open a new Terminal tab and type
killall [process name]
where [process name] is the name of your bash script (you can find this in OS X's Activity Monitor).
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 &&‘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?)
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.
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
-vvvto avoid the script not exiting cleanly and completely.If, however, you have to use the verbosity option
-vvvaddnohupbefore 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
To cancel execution of the command, completely erase the contents of the file before saving it and quitting the editor.
Interestingly, using this method, the original unedited command is still saved in the history.
Note: this answer was suggested in a comment -- I tested it and it works.
Even in the course of normal line editing, I've cultivated the habit of putting a # prefix at the beginning of the line. This allows me to look over a complex command to ensure that it's correct, or perhaps to save a "draft" of a command in my history while I go research some other point of information that I need to formulate and check the precise syntax of the draft command.
Presuming you're editing just a one-line command, from within vi, do:
1Gi#Esc
Then save the file, and your "draft" command will not be executed, but will be stored in your bash history. When you're ready, you can return to the command, remove the leading # and execute the command.
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.
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
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?