22

Sometimes you run a program from the terminal, say, lxpanel. The terminal won't drop you back to the prompt, it'll hang. You can press Ctrl+C to get back to the prompt, but that will kill lxpanel. However, pressing Alt+F2 (which pops up a window to take a command) and running lxpanel works gracefully.

Why is this? What is different between running a command from the terminal and from the 'run' window that appears when you press Alt+F2?

lxpanel here was just used as an example. I have experienced this with multiple programs

  • 1
    Tip: GNU Screen (screen) can, among other things, be used to "wrap" longer-running processes. You can detach from it, going back to shell, then reattach and see output from the running process. Reattachment can even be done from another terminal, SSH etc. There may also be other programs that let you do this sort of thing. – poplitea Dec 28 '11 at 7:10
28

By default the terminal will run the program in the foreground, so you won't end up back at the shell until the program has finished. This is useful for programs that read from stdin and/or write to stdout -- you generally don't want many of them running at once. If you want a program to run in the background, you can start it like this:

$ lxpanel &

Or if it's already running, you can suspend it with Ctrl+Z and then run bg to move it into the background. Either way you will end up with a new shell prompt, but the program is still running and its output will appear in the terminal (so it can suddenly show up while you're in the middle of typing)

Some programs (typically daemons) will fork a separate process when they start, and then let the main process immediately exit. This lets the program keep running without blocking your shell

  • So what is the system actually doing when you run the program via the 'run' window by pressing Alt + f2? (at least on gnome and openbox, alt+f2 does that). I ask because as soon as you type the command, the program starts and the box goes away. is it just adding a & to it? – sqram Dec 26 '11 at 10:05
  • 2
    @lyrae: by default, the shell waits for the program to complete before continuing the shell session, it does not "hang", by any definition of "hang"; alt+f2 does not wait for the program. The reason the shell waits for the program to complete is because the shell can redirect whatever the user typed into the shell to the program's standard input and/or display program's standard output. Since alt+f2 is primarily used for starting a GUI program, alt+f2 do not provide the possibility of using standard input/output and so it do not need to wait. – Lie Ryan Dec 26 '11 at 10:20
  • 1
    @lyrae: alt+f2 does not do anything special to start the program in background; it is the shell that's doing something special, adding '&' is the shell's functionality. When starting a command without a '&', the shell redirects the program's standard input to its own standard input and the program's standard output to its own standard output (a bit contrived, since the shell also provides many other services, such as intercepting Ctrl-C, to send a SIGINT signal command to the foreground program). The '&' tells the shell not to do those and just start the program (also contrived). – Lie Ryan Dec 26 '11 at 10:31
  • 1
    @LieRyan some of what you're saying the shell does is in fact handled by the kernel's terminal driver, and "with &" is generally more "special" than "without &", other than that the shell calls wait() [or waitpid or equivalent] which isn't done by alt-f2. – Random832 Dec 26 '11 at 18:12
6

When you start a program in a terminal, the terminal will "hang" until your program stops. By pressing Ctrl+c you are closing your program, and thus get back to the prompt. You will see this with all GUI apps, try Firefox, for example.

When you use some other method such as Alt+F2 or clicking through the menus, your program is started in the background so nothing weird happens (and there is no command prompt anyway).

If you still want to launch GUI apps from the terminal, append & at the end of your command, like so

lxpanel &

This tells the terminal to run lxpanel in the background and give you another prompt immediatelly.

3

Programs run via a shell run in the foreground of that shell by default. This causes the shell to suspend operation and direct stdin/stdout/sterr from the terminal to the program. Programs run via the desktop environment are forked, which causes them to run independent of the program that ran them. This can be simulated in most shells by appending a & to the command, although this will still connect std* to the terminal (although reading from stdin on a backgrounded program has further complications).

2

The & backgrounds well except for programs that come back requiring console interaction later on (for example, an "apt -y update &" that eventually enters the STOP state since it's wanting to prompt the user a "really really force?" question much later....when no one is watching anymore).

To plug that hole and inform the process a terminal will really never never become available to it, I append a <&- to some of my commands, completely detaching them from the active terminal telling them STDIN is no longer possible. Make sure /bin/bash is your shell if you use that though. The script will carry on logging any errors related to no pseudoterminal being available on which to cast any prompt.

For example:

`./runme.sh &> runme.log <&- & disown`

is my ultimate way of disassociating from current terminal session. Both STDOUT and STDERR get logged to runme.log, it won't matter if your console or shell terminate sooner or if you logout/su to a different account (no terminal garbage from runme), and thanks to disown even the parent-child PID relationship is removed.

UPDATE: even with that I've had trouble with a semaphore associating it with the name of the original parent, so now I recommend instead:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Of course, remove the &> if you want to get emailed the output from CRON, or redirect it all to /dev/null instead of a file.

  • A slightly less convoluted way to achieve that I began using is at now <<< "(cmd1; cmd2; etc.) &> logfile.log" – Marcos Jan 31 '12 at 11:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.