Why do some commands ‘hang’ the terminal until they’ve finished?

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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

Method 2

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.

Method 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).

Method 4

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.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x