I am using this command kill -s SIGINT ps on the command line and it works (the process is eliminated), but when I use that command on a SHELL script it doesn´t work and it shows this error message kill: SIGNIT: invalid signal specification. How can I solve this. Thanks
Error messages exist to give developers, and also users, a clue when something goes wrong. I suspect that you're mistyping SIGINT as SIGNIT. The error message you're getting is consistent with a typo in your statement.
I feel like this shows poor research effort because if you had read the error message before asking help, you would have figured it out.
I would like to answer this because I solved the similar problem recently. When you call kill -s SIGINT, you may use sh to run the script. Unfortunately, sh which is different from bash(linux shell kill signal SIGKILL && KILL) will run in compatibility mode and not recognize SIGINT.
The best solution is to use /bin/bash explicitly. By the way, #!/bin/bash doesn't work when you sh the script, either.
Hope it helps.
It's possible that the shell executing the script is using a built-in "kill" command while your command-line shell is using an external binary, or vice-versa. Use /bin/kill explicitly and see if that helps be more consistent. kill -SIGINT is, I believe, the more common way of doing this (instead of "-s SIGINT").
Also, kill normally takes a process-id and not a process-name. Built-in vs external "kill" commands may also support (or not support) this differently.
Related
I have a bit of an interesting situation that I can't figure out.
I need the ability to issue a command remotely over SSH, which then pipes the results into an ncat tunnel back to the original server.
My commands are a little more complex than this (involving innobackupex, a MySQL backup utility), but this minimal example shows the same issue:
ncat -l 9970 &
ssh db-202 "echo 'testing' | ncat $BACKUPSERVER 9970"
... other commands
The issue is that after the echo command completes (or whatever is run), the script just hangs and the later commands don't run. I need to send a ctrl-c (SIGINT) to continue. Obviously this isn't ideal in the context of a bash script, where lots of things may need to happen after this command completes automatically.
Not sure if it's relevant, but sending a sigint doesn't always properly terminate the ncat tunnel on both sides. Sometimes I need to kill -9 it, probably due to the sigint messing something up.
Can anybody explain this behavior and how I can get around it? Or a better way to do what I want?
Thanks!
Finally figured it out.
I added the --recv-only and --send-only arguments to each side of the tunnel.
According to the manpage:
--send-only Only send data, ignoring received; quit on EOF
This may explain it, but I though that any EOF would terminate the tunnel. Maybe without these arguments, both sides need to send an EOF?
Anyway, here are the commands that work.
ncat --recv-only -l 9970 &
ssh db-202 "echo 'testing' | ncat --send-only $BACKUPSERVER 9970"
Hopefully this helps someone in the future.
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 need to kill a process using the same command in both sh and bash (In a script). Normally I would do the following in bash:
SCRIPT=$(basename $0) #So the script knows itself
killall -9 $SCRIPT #Kill itself
However this does not seem to work using SH
Any suggestions on a solution that will work in either.
Is there an easier or more correct way to completely exit a script. Seems I have revisited this question many times over the years and never found the official correct way.
Basically to let the script kill itself, point it to $$ which presents the process ID of the shell.
kill "$$"
Avoid SIGKILL (9) when not necessary. Only use it on applications that get significantly unresponsive.
The default signal sent is SIGTERM (15), and there are other signals that could also terminate the process which may be safer than SIGKILL. One of those are SIGQUIT, SIGABRT, and SIGHUP.
Well, what I need to do actually is CTRL-Z out of a process that got started from insert mode in GVim.
My command :Cdprun executes cdprun.sh which runs a sudo-ed daemon. I can add & at the end of the sudo-ed daemon call to run in the background and that works but the user doesn't get prompted for a password. Instead I want to just CTRL-Z out of it but the keyboard interrupt doesn't work. Any ideas? Thx.
You generally have two options in this case: generic is using something like vim-addon-async mentioned by #Nicalas Martin or vim with built-in interpreters support: tcl with expect module, python with pyexpect, perl with Expect, maybe something else (note: all of the mentioned packages are not shipped with tcl/python/perl). Second is specific to current situation: it is backgrounding in the other place. From your explanation I guessed that you have a script looking like
#!/bin/sh
<...>
sudo run-daemon --daemon-args # Last executed line
, am I right? Than you can just put backgrounding in another place: not
sudo run-daemon --daemon-args &
, but
sudo sh -c "nohup run-daemon --daemon-args &"
Here is a script to deal with asynchronous command in vim. Not a perfect solution but could be a good temporary solution. http://www.vim.org/scripts/script.php?script_id=3307
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.