I tried killing a process with shell in Ubuntu which is created with like:
#!/bin/bash
<!--There should be codes which can kill my app(run in the background)
echo "app will be run."
java -jar path/to/my/jar/file.jar /arguman/of/myApp.txt & << 'ENDAPP'
disown ENDAPP
I know how to kill an app with manuel which is like:
ps -ax -u| grep appName
and find processid then,
kill [processId]
Is it possible to do?İf yes,how?
Thank you.
You can actually find examples of how to do this right here, on this site, by doing a simple search. (Or Google it: "bash shell wait.") When you execute any background process, you can get the PID ("process id") of the new child. You can wait on the child to finish. You can also kill it.
Shell commands that show you executing jobs also provide their PID.
However, bear in mind that "killing a child" ... while it won't land you in prison in this case ;-) ... "is generally not a good thing to do." You have no idea what the child was doing, what it had or had not finished doing, what data might now be in an inconsistent state, when you put that bullet through its brain. It is impossible to reliably debug any process that relies on murdering its children.
You can "send a different signal," such as SIGHUP or SIGUSR1, to a process, using the same kill command, and design the child process to be listening for that signal as an indication that it must "shut itself down, quickly." Always give a process a signal to "put its own affairs in order, and then to leave 'this mortal coil' ..."
Related
I'm sure this is really simple, but it's biting me in the face anyway, and I'm a little frustrated and stumped.
So, I have a script which I've managed to boil down to:
#!/bin/sh
sleep 50 | echo
If I run that at the command line, and hit Ctrl-C it stops, like I would expect.
If I send it sigint, using kill, it does nothing.
I thought that was strange, since I thought those should have been the same.
Then, if I send it sigterm, then it also dies, but if I look in ps, the sleep is still running.
What am I missing, here?
This is obviously not the real script, which runs python, and it's more of a problem when it keeps running after start-stop-daemon tries to kill the daemon.
Help me people. I'm dumb.
The reason this happens is that the Ctrl-C is delivered to the sleep process, whereas the sigint you are sending is delivered only to the script itself. See Child process receives parent's SIGINT for details on this.
You can verify this yourself by using strace -p when hitting ctrl-c or sending sigint; strace will tell you what signals are delivered.
EDIT: I don't think you are dumb. Processes and how they work are seemingly simple, but the details are often complicated, and even experts get confused by this sort of thing.
I did the same thing I written script named as test.sh with below containt.
#!/bin/sh
sleep 50 | echo
After executing , I did Ctrl-C -> its working fine means closing it.
Again executed and in another terminal i checked the PID by ps -ef|grep test.sh after finding the pid , i did kill <pid> and it killed the process , to verify again i executed ps -ef|grep test.sh and didnt get any pid.
I have a script that launches another script in the background, and then terminates it. I was expecting the child script to be gone, but in the end it still manages to print some output. Here is the example:
in script one.sh:
echo "this is one"
./two.sh &
sleep 1
pid=$!
kill $pid
echo "this was one"
in script two.sh:
echo "this is two"
./three.sh
echo "this was two"
in script three.sh:
echo "this is three"
sleep 5
echo "this was three"
I ran ./one.sh which is supposed to run two.sh in the background, which in turn runs three.sh but not in the background! The output is get is:
this is one
this is two
this is three
this was one
this was three
Shouldn't "this was three" not appear in the output since three.sh was not ran in the background and two.sh was terminated by one.sh? Could you also point me towards any documentation that describes how processes behave when (not) in background and what happens when they are terminated?
Thank you very much for all your help!
When you start a new process from a bash script this is basically done via fork() .
The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent (except for a number of points that can be found in man fork).
If a parent dies the child becomes a child of the init process.
Then it is the role of the init process to collect the return code of the child (reaping) after it has exited. So when you kill "two", "three" isn't killed but just gets a different parent. And this is the reason for the trailing three.
The question is discussed from a C-point-of-view here : How to make child process die after parent exits?
You're killing the backgrounded process two.sh, but not two.sh and its child three.sh.
This question:
Best way to kill all child processes
has more info on killing child processes.
The reason this may seem surprising is that one might expect the TERM signal (the default from "kill") to be propagated to child processes, in other words, that the SIGTERM signal (signal #15) received by two.sh would be propagated to three.sh as well. However, this is not actually the case. Killing two.sh simply leaves three.sh to be fostered out to the "init" process (proceess ID 1) as its new parent process, and init will clean up after three.sh when it exits.
The situation gets more complicated with process groups, and the bash documentation talks about how keyboard-generated signals get send to all processes within the foreground process group, often a pipeline being run without an "&" on the end. However, these issues don't apply to the example scripts.
Note: In Unix, you shouldn't use ".sh" extensions on executable scripts. Focus on putting the right "#!/bin/bash" or "#!/bin/sh" on the first line instead. Commands should not expose their implementation language in the command name, lest one have to leave the wrong one on later when the implementation language changes, but other code has come to rely on the original, now incorrect extension.
I have a script for launchd to run that starts a server, then tells it to exit gracefully when launchd kills it off (which should be at shutdown). My question: what is the appropriate, idiomatic way to tell the script to idle until it gets the signal? Should I just use a while-true-sleep-1 loop, or is there a better way to do this?
#!/bin/bash
cd "`dirname "$0"`"
trap "./serverctl stop" TERM
./serverctl start
# wait to receive TERM signal.
You can simply use "sleep infinity". If you want to perform more actions on shutdown and don't want to create a function for that, an alternative could be:
#!/bin/bash
sleep infinity & PID=$!
trap "kill $PID" INT TERM
echo starting
# commands to start your services go here
wait
# commands to shutdown your services go here
echo exited
Another alternative to "sleep infinity" (it seems busybox doesn't support it for example) could be "tail -fn0 $0" for example.
A plain wait would be significantly less resource-intensive than a spin lock, even with a sleep in it.
Why would you like to keep your script running? Is there any reason? If you don't do anything later after signal then I do not see a reason for that.
When you get TERM from shutdown then your serverctl and server executable (if there is any) also gets TERM at the same time.
To do this thing by design you have to install your serverctl script as rc script and let init (start and) stop that. Here I described how to set up server process that is not originally designed to work as server.
I've seen monitoring programs either in scripts that check process status using 'ps' or 'service status(on Linux)' periodically, or in C/C++ that forks and wait on the process...
I wonder if it is possible to use bash with trap and restart the sub-process when SIGCLD received?
I have tested a basic suite on RedHat Linux with following idea (and certainly it didn't work...)
#!/bin/bash
set -o monitor # can someone explain this? discussion on Internet say this is needed
trap startProcess SIGCHLD
startProcess() {
/path/to/another/bash/script.sh & # the one to restart
while [ 1 ]
do
sleep 60
done
}
startProcess
what the bash script being started just sleep for a few seconds and exit for now.
several issues observed:
when the shell starts in foreground, SIGCHLD will be handled only once. does trap reset signal handling like signal()?
the script and its child seem to be immune to SIGINT, which means they cannot be stopped by ^C
since cannot be closed, I closed the terminal. The script seems to be HUP and many zombie children left.
when run in background, the script caused terminal to die
... anyway, this does not work at all. I have to say I know too little about this topic.
Can someone suggest or give some working examples?
Are there scripts for such use?
how about use wait in bash, then?
Thanks
I can try to answer some of your questions but not all based on what I
know.
The line set -o monitor (or equivalently, set -m) turns on job
control, which is only on by default for interactive shells. This seems
to be required for SIGCHLD to be sent. However, job control is more of
an interactive feature and not really meant to be used in shell scripts
(see also this question).
Also keep in mind this is probably not what you intended to do
because once you enable job control, SIGCHLD will be sent for every
external command that exists (e.g. every time you run ls or grep or
anything, a SIGCHLD will fire when that command completes and your trap
will run).
I suspect the reason the SIGCHLD trap only appears to run once is
because your trap handler contains a foreground infinite loop, so your
script gets stuck in the trap handler. There doesn't seem to be a point
to that loop anyways, so you could simply remove it.
The script's "immunity" to SIGINT seems to be an effect of enabling
job control (the monitor part). My hunch is with job control turned on,
the sub-instance of bash that runs your script no longer terminates
itself in response to a SIGINT but instead passes the SIGINT through to
its foreground child process. In your script, the ^C i.e. SIGINT
simply acts like a continue statement in other programming languages
case, since SIGINT will just kill the currently running sleep 60,
whereupon the while loop will immediately run a new sleep 60.
When I tried running your script and then killing it (from another
terminal), all I ended up with were two stray sleep processes.
Backgrounding that script also kills my shell for me, although
the behavior is not terribly consistent (sometimes it happens
immediately, other times not at all). It seems typing any keys other
than enter causes an EOF to get sent somehow. Even after the terminal
exits the script continues to run in the background. I have no idea
what is going on here.
Being more specific about what you want to accomplish would help. If
you just want a command to run continuously for the lifetime of your
script, you could run an infinite loop in the background, like
while true; do
some-command
echo some-command finished
echo restarting some-command ...
done &
Note the & after the done.
For other tasks, wait is probably a better idea than using job control
in a shell script. Again, it would depend on what exactly you are trying
to do.
I wanted to know why i am seeing a different behaviour in the background process in Bash shell
Case 1: Logged in to Unix server using Putty(SSH)
By default it uses csh shell
I changed to bash shell
typed sleep 2000 &
press enter
It gave me the job number. Now i killed my session by clicking the x in the putty window
Now open another session and tried to lookup the process..the process died.
Case 2:Case 1: Logged in to Unix server using Putty(SSH)
By default it uses csh shell
I changed to bash shell
vi mysleep.sh
sleep 2000 & Saved mysleep.sh
./mysleep.sh
Diff here is..instead of executing the sleep command directly i am storing the sleep command in a file and executing the file.
Now i killed my session by clicking the x in the putty window
Now open another session and tried to lookup the process..the process is still there
Not sure why this is happening. I thought i need to do disown in bash to run the process even after logging out.
One diff i see in the parent process id..In the second case..the parent process id for the sleep 2000 becomes 1. Looks like as soon as process for mysleep.sh died the kernel assigned the parent process to 1.
The difference here is indeed the intervening process.
When you close the terminal window, a HUP signal (related to "nohup" as an0nymo0usc0ward mentioned) is sent to the processes running in it. The default action on receiving HUP is to die - from the signal(3) manpage,
No Name Default Action Description
1 SIGHUP terminate process terminal line hangup
In your first example, the sleep process directly receives this HUP signal and dies because it isn't set to do anything else. (Some processes catch HUP and use it to perform some action, e.g. reread some configuration files)
In the second example, the shell process running your shell script has already died, so the sleep process never gets the signal. In UNIX, every process must have a parent process due to the internals of how the wait(2) family of calls works and indeed processes in general. So when the parent process dies, the kernel gives it to init (pid 1, as you note) as a foster child.
Orphan process (on wikipedia) has some more information available about it, also see Zombie process for some additional technical details.
Already running process?
^z
bg
disown %<jobid>
New process/script (on local machine's console)?
nohup script.sh &
New process/script (on remote machine's console)?
Depending on your need,
there are two options [ there will be more ;-) ]
ssh remotehost 'nohup /path/to/script.sh </dev/null > nohup.out 2>&1 &'
OR
use 'screen'
Try "nohup cmd args..."
Steven's answer is correct, but I'd like to highlight the tricky part here again:
=> Using a bash script that just executes sleep in the background
The effect of this is that the "script" exits almost immediately (since it's done all its commands). However, it did create a child process (sleep) during its lifetime. The effect of this is that:
The "script" cannot be the parent anymore, and sleep is orphaned to init (which shows nicely in a pstree)
The bash shell where you started the script from has no underlying jobs anymore
Note that this stuff all happens when you executed the script, and has nothing to do with any ssh logout/putty closing.
When you then finally close your putty session, bash receives a "SIGHUP", but doesn't forward it to any other process (since there are no jobs left)
In the other case, bash did still have a job left, which it then sent the SIGHUP to, causing it to end (as you noticed)
Hope this helps