Proper way to exit command line program? - unix

I'm using mac/linux and I know that ctrl-z stops the currently running command in terminal, but I frequently see the process is still running when i check the system monitor. What is the right way to stop a command in terminal?
Typically I run into this issue when running python or ruby apps, i'm not sure if that has something to do with it, just thought I would add that.

Using control-z suspends the process (see the output from stty -a which lists the key stroke under susp). That leaves it running, but in suspended animation (so it is not using any CPU resources). It can be resumed later.
If you want to stop a program permanently, then any of interrupt (often control-c) or quit (often control-\) will stop the process, the latter producing a core dump (unless you've disabled them). You might also use a HUP or TERM signal (or, if really necessary, the KILL signal, but try the other signals first) sent to the process from another terminal; or you could use control-z to suspend the process and then send the death threat from the current terminal, and then bring the (about to die) process back into the foreground (fg).
Note that all key combinations are subject to change via the stty command or equivalents; the defaults may vary from system to system.

if you do ctrl-z and then type exit it will close background applications.
Ctrl+Q is another good way to kill the application.

Take a look at Job Control on UNIX systems
If you don't have control of your shell, simply hitting ctrl + C should stop the process. If that doesn't work, you can try ctrl + Z and using the jobs and kill -9 %<job #> to kill it. The '-9' is a type of signal. You can man kill to see a list of signals.

Related

Signals and Interupts When Executing a Program and Killing it

I want to understand better the signals and interupts mechanism in UNIX OS. As far as I understand it, interrupts are used to communicate between the CPU and the OS kernel. Signals are used to communicate between the OS kernel and OS processes.
I'm having some hard time understanding what happened on certain scenarios, and finding which signals and interrupts are being called and when.
For example, when executing a program and killing it using kill pid. Which interrupts are being triggered when typing the name of the program in the shell (e.g. pluma and then kill pluma_id)?
I've tried to use strace when calling the kill command. The first command that is executed is: execve ("/bin/kill", ["kill", "10057"], [/* 47 cars */]) = 0
As far as I see, this is a standard syscall, but I cannot understand which interrupts were triggered and which signals were sent when the keyboard key-down-event has happened. I also cannot understand which signals were sent to the process when it was killed using the kill syscall (maybe it wasn't sent at all?).
What is the full sequence of events (signals, sisals and interrupts) that happens in the following scenario:
Typing plume in shell
Hitting the enter key and executing pluma
Executing kill pluma_id
(Concise description is more than enough, just to understand the general flow)
Typing plume in shell
Keyboard interrupts occur. The CPU receives the keyboard interrupts, executes the handler, reads the keycode and scan code etc. An event in generated in /dev/input/event* which will be read either by a terminal emulator program or will get forwarded to the program by your input system. Your desktop environment, Xserver etc are involved.
Hitting the enter key and executing pluma
Same as above. Upon receiving the enter key, the shell would fork() and exec() pluma.
Executing kill pluma_id
Shell process makes the kill() system call. My manual for kill says "The default signal for kill is TERM. Use -l or -L to list available signals". There will be a context switch when the system call is made. After verifying the permissions, the kernel would find the process table entry for the specified process ID. It will update the signal mask for the process in the PTE with the signal number pluma has received.
Thus the signal is delivered to the process. Now the process needs to handle the signal. If it has installed a signal handler for the particular signal, the handler gets called. Else a default handeler/action will be taken by the kernel. In unix systems, signal handling for a process usually happens during a context switch, ie, when the process switches back to user context or when the process gets scheduled again.
The Design of the UNIX Operating System by Maurice J. Bach has a very simple and detailed explanation of the whole process. You might want to have a look at it.
Underneath kill (the program) used is a kill() system call, and this system call always gets a signal number as an argument.
The command kill just assumes that certain signals are sent by default, e.g.: TERM signal. What you look at strace output is program invocation. You should look deeper into the trace, and find where the system call is called. And then you'll see a numerical value of the signal.
You should take a look at the kill program documentation I think. It mentions which signal is sent to the process by default, if you don't specify the signal explicitly. It also shows you how to send a specific signal, if you want to.

How to detach a process from terminal in unix?

When I start a process in background in a terminal and some how if terminal gets closed then we can not interact that process any more. I am not sure but I think process also get killed. Can any one please tell me how can I detach that process from my terminal. So even if I close terminal then I can interact with same process in new terminal ?
I am new to unix so your extra information will help me.
The command you're looking for is disown.
disown <processid>
This is as close as you can get to a nohup. It detaches the process from the current login and allows it to continue running. Thanks David Korn!
http://www2.research.att.com/~gsf/man/man1/disown.html
and I just found reptyr which lets you reparent a disowned process.
https://github.com/nelhage/reptyr
It's already in the packages for ubuntu.
BUT if you haven't started the process yet and you're planning on doing this in the future then the way to go is screen and tmux. I prefer screen.
You might also consider the screen command. It has the "restore my session" functionality. Admittedly I have never used it, and forgot about it.
Starting the process as a daemon, or with nohup might not do everything you want, in terms of re-capturing stdout/stdin.
There's a bunch of examples on the web. On google try, "unix screen command" and "unix screen tutorial":
http://www.thegeekstuff.com/2010/07/screen-command-examples/
GNU Screen: an introduction and beginner's tutorial
First google result for "UNIX demonizing a process":
See the daemon(3) manpage for a short overview. The main thing of daemonizing
is going into the background without quiting or holding anything up. A list of
things a process can do to achieve this:
fork()
setsid()
close/redirect stdin/stdout/stderr to /dev/null, and/or ignore SIGHUP/SIGPIPE.
chdir() to /.
If started as a root process, you also want to do the things you need to be root
for first, and then drop privileges. That is, change effective user to the "daemon"
user or "nobody" with setuid()/setgid(). If you can't drop all privileges and need
root access sometimes, use seteuid() to temporary drop it when not needed.
If you're forking a daemon then also setup child handlers and, if calling exec,
set the close on exec flags on all file descriptors your children won't need.
And here's a HOWTO on creating Unix daemons: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html
'Interact with' can mean a couple of things.
The reason why a program, started at the command-line, exits when the terminal ends, is because the shell, when it exits, sends that process a HUP signal (see documentation for kill(1) for some introduction; HUP, by the way, is short for 'hang up', and originally indicated that the user had hung up the modem/telephone). The default response to a HUP signal is that a process is terminated – that is, the invoked program exits.
The details are slightly more fiddly, but this is the general intuition.
The nohup command tells the shell to start the program, and to do so in a way that this HUP signal is ignored. That is, the program keeps going after the invoking terminal exits.
You can still interact with this program by sending it signals (see kill(1) again), but this is a very limited sort of interaction, and depends on your program being written to do sensible things when it receives those signals (signals USR1 and USR2 are useful things to trap, if you're into that sort of thing). Alternatively, you can interact via named pipes, or semaphores, or other bits of inter-process communication (IPC). That gets fiddly pretty quickly.
I suspect what you're after, though, is being able to reattach a terminal to the process. That's a rather more complicated process, and applications like screen do suitably complicated things behind the scenes to make that happen.
The nohup thing is a sort of quick-and-dirty daemonisation. The daemon(3) function does the daemonisation 'properly', doing various bits of tidy-up as described in YePhIcK's answer, to comprehensively break the link with the process/terminal that invoked it. You can interact with that daemonised process with the same IPC tools as above, but not straightforwardly with a terminal.

Unix Background process STOPPED abnormally

I executed a perl script in background using the following command
nohup perl myPerlSCript.pl >debug_log &
After few minutes I got the status as
[1]+ Stopped
I wasn't expecting it to stop, nor do I know what stopped it. How can I debug this and find out why it stopped? I am actually interested in knowing the unix commands to debug.
There are several ways a process running in the background can be stopped. All of them involve one of these signals:
SIGSTOP
SIGTSTP
SIGTTOU
SIGTTIN
SIGSTOP is severe. It's unblockable, unignorable, unhandlable. It stops the process as surely as SIGKILL would kill it. The others can be handled by the background process to prevent stopping.
A signal was sent by another process using kill(2), or by the process to itself using raise(3) or kill(2)
The process attempted to write to the terminal, and the terminal option tostop is enabled (see output of stty -a). This generates SIGTTOU.
The process attempted to change the terminal modes with tcsetattr(3) or an equivalent ioctl. (These are the same modes shown by stty.) This generates SIGTTOU regardless of the current state of the tostop flag.
The process attempted to read from the terminal. This generates SIGTTIN.
This list is probably very incomplete.
Are you using tcsh by any chance? Tcsh actually comes with a built-in nohup command that I've had lots of problems with before, seeing the exact behavior you're seeing.
Try using /usr/bin/nohup directly if that is the case.

Difference between process group id and job id in UNIX

Please tell me the difference between a process group ID and a jobid. Is jobid a builtin of a shell program or is it related to the kernel? What are the uses of each of them? When a process is run in background, is only jobid set or is the pgid set as well?
What are the uses of the setpgid() function?
When a process is run in background, is the kernel also involved or does the shell take care of which is background or foreground?
Good questions. The job id is mostly just a shell construct. There is support in the kernel in the form of the signals that are involved in job control, and the way in which the kernel knows exactly which processes to send the job control signals to.
Strictly speaking, the answer to your first question is that the job id is purely a shell creation. It exists because a pipeline (or, rarely, another shell grouped construct) may consist of multiple processes that should be controlled as a unit.
To answer your last question, the shell starts all processes by first doing a fork(2) and then doing an execve(2). The only difference with & is that the shell does not do a wait(2) (or a related variant) and so the program can continue "in the background". There is actually little distinction in Unix between foreground and background.
The process group is an association defined by shells so that the kernel knows about a single "foreground" process that handles a set of various "background" processes. This is mainly important so that the background processes will generate a signal should they decide to suddenly read from a terminal. (Such terminal probably being connected to standard input.) This will cause the "job" to generate a signal and the shell will prompt the user to do something.
Try (sleep 5; read x)& and after 6 seconds type a return or something so that the shell wakes up. That's when you see something like...
[1]+ Stopped ( sleep 5; read x )
...and you then type fg to pull it into the foreground.
Originally, Unix had pipelines, and it had &, but there was no way to move a command or pipeline between foreground and background and no way to help a background process that suddenly decided to read standard input.
Job control and the kernel support for it were added by Bill Joy and others in early versions of BSD and csh(1). These were picked up line-for-line by commercial Unix and in cloned for the work-alike Linux kernel.
Regarding the questions about process groups and ps(1)...
In order to support job control in shells, the kernel process state includes a process group ID and a session ID. A process group and a job are the same thing, but a job number is just a handle the shell makes up. A process is a session leader if the session ID is the same as the pid, and a process is a process group leader if the pgid is the same as the pid. I believe something a bit more subtle is happening with the + that ps(1) prints. Each terminal knows what its foreground process group is, so I believe a process gets a + if pid == pgid && (pgid is the foreground pg for its controlling terminal).
In summary, the kernel keeps several items of state: pid, pgid, sid, and a process may have a controlling terminal and a terminal may have a foreground pgid. These credentials are mostly intended to support job control but are also used to revoke access to a terminal when a user logs out.

Tie the life of a process to the shell that started it

In a UNIX-y way, I'm trying to start a process, background it, and tie the lifetime of that process to my shell.
What I'm talking about isn't simply backgrounding the process, I want the process to be sent SIGTERM, or for it to have an open file descriptor that is closed, or something when the shell exits, so that the user of the shell doesn't have to explicitly kill the process or get a "you have running jobs" warning.
Ultimately I want a program that can run, uniquely, for each shell and carry state along with that shell, and close when the shell closes.
IBM's DB2 console commands work this way. When you connect to the database, it spawns a "db2bp" process, that carries the database state and connection and ties it to your shell. You can connect in multiple different terminals or ssh connections, each with its own db2bp process, and when those are closed the appropriate db2bp process dies and that connection is closed.
DB2 queries are then started with the db2 command, which simply hands it off to the appropriate db2bp process. I don't know how it communicates with the correct db2bp process, but maybe it uses the tty device connected to stdin as a unique key? I guess I need to figure that out too.
I've never written anything that does tty manipulation, so I have no clue where to even start. I think I can figure the rest out if I can just spawn a process that is automatically killed on shell exit. Anyone know how DB2 does it?
If your shell isn't a subshell, you can do the following; Put the following into a script called "ttywatch":
#!/usr/bin/perl
my $p=open(PI, "-|") || exec #ARGV; sleep 5 while(-t); kill 15,$p;
Then run your program as:
$ ttywatch commandline... & disown
Disowning the process will prevent the shell from complaining that there are running processes, and when the terminal closes, it will cause SIGTERM (15) to be delivered to the subprocess (your app) within 5 seconds.
If the shell isn't a subshell, you can use a program like ttywrap to at least give it its own tty, and then the above trick will work.
Okay, I think I figured it out. I was making it too complicated :)
I think all db2 is daemon-izing db2bp, then db2bp is calling waitpid on the parent PID (the shell's PID) and exiting after waitpid returns.
The communication between the db2 command and db2bp seems to be done via fifo with a filename based on the parent shell PID.
Waaaay simpler than I was thinking :)
For anyone who is curious, this whole endeavor was to be able to tie a python or groovy interactive session to a shell, so I could test code while easily jumping in and out of a session that would retain database connections and temporary classes / variables.
Thank you all for your help!
Your shell should be sending a SIGHUP signal to any running child processes when it shuts down. Have you tried adding a SIGHUP handler to your application to shut it down cleanly
when the shell exits?
Is it possible that your real problem here is the shell and not your process. My understanding agrees with Jim Lewis' that when the shell dies its children should get SIGHUP. But what you're complaining about is the shell (or perhaps the terminal) trying to prevent you from accidentally killing a running shell with active children.
Consider reading the manual for the shell or the terminal to see if this behavior is configurable.
From the bash manual on my MacBook:
The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP
to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To
prevent the shell from sending the signal to a particular job, it should be removed from the jobs table with
the disown builtin (see SHELL BUILTIN COMMANDS below) or marked to not receive SIGHUP using disown -h.
If the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an interactive
login shell exits.
which might point you in the right direction.

Resources