Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I find it hard to phrase the question precisely but I will give my best. I use dwm as my default window manager and dmenu as my application launcher. I hardly use GUI applications aside from my browser. Most of my work is done directly from the command line. Furthermore, I'm a great fan of minimalism regarding operating systems, applications etc. One of the tools I never got rid of was an application launcher. Mainly because I lack a precise understanding of how application launchers work/what they do. Even extensive internet search only shows up vague explanation. What I want to do is get rid even of my application launcher because apart from actually spawning the application I have absolutely no use for it. In order to do this I would really like to know how to "correctly" start applications from the shell. Whereby the meaning of "correctly" can be approximated by "like an application launcher would do". I do not claim that all application launchers work the same way because I do not understand them well enough.

I know about the following ways to spawn processes from the shell:

  1. exec /path/to/Program replace shell with the specified command without creating a new process
  2. sh -c /path/to/Program launch shell dependent process
  3. /path/to/Program launch shell dependent process
  4. /path/to/Program 2>&1 & launch shell independent process
  5. nohup /path/to/Program & launch shell independent process and redirect output to nohup.out

Update 1: I can illustrate what e.g. dmenu does reconstructing it from repeated calls to ps -efl under different conditions. It spawns a new shell /bin/bash and as a child of this shell the application /path/to/Program. As long as the child is around so long will the shell be around. (How it manages this is beyond me...) In contrast if you issue nohup /path/to/Program & from a shell /bin/bash then the program will become the child of this shell BUT if you exit this shell the program's parent will be the uppermost process. So if the first process was e.g. /sbin/init verbose and it has PPID 1 then it will be the parent of the program. Here's what I tried to explain using a graph: chromium was launched via dmenu, firefox was launched using exec firefox & exit:

systemd-+-acpid
        |-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
        |                 |                           `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
        |                 |                                                    |-{Compositor}]
        |                 |                                                    |-{HTMLParserThrea}]
        |                 |                                                    |-{OptimizingCompi}]
        |                 |                                                    `-3*[{v8:SweeperThrea}]]
        |                 |-chromium
        |                 |-chromium-+-chromium
        |                 |          |-{Chrome_ChildIOT}
        |                 |          `-{Watchdog}
        |                 |-{AudioThread}
        |                 |-3*[{BrowserBlocking}]
        |                 |-{BrowserWatchdog}
        |                 |-5*[{CachePoolWorker}]
        |                 |-{Chrome_CacheThr}
        |                 |-{Chrome_DBThread}
        |                 |-{Chrome_FileThre}
        |                 |-{Chrome_FileUser}
        |                 |-{Chrome_HistoryT}
        |                 |-{Chrome_IOThread}
        |                 |-{Chrome_ProcessL}
        |                 |-{Chrome_SafeBrow}
        |                 |-{CrShutdownDetec}
        |                 |-{IndexedDB}
        |                 |-{LevelDBEnv}
        |                 |-{NSS SSL ThreadW}
        |                 |-{NetworkChangeNo}
        |                 |-2*[{Proxy resolver}]
        |                 |-{WorkerPool/1201}
        |                 |-{WorkerPool/2059}
        |                 |-{WorkerPool/2579}
        |                 |-{WorkerPool/2590}
        |                 |-{WorkerPool/2592}
        |                 |-{WorkerPool/2608}
        |                 |-{WorkerPool/2973}
        |                 |-{WorkerPool/2974}
        |                 |-{chromium}
        |                 |-{extension_crash}
        |                 |-{gpu-process_cra}
        |                 |-{handle-watcher-}
        |                 |-{inotify_reader}
        |                 |-{ppapi_crash_upl}
        |                 `-{renderer_crash_}
        |-2*[dbus-daemon]
        |-dbus-launch
        |-dhcpcd
        |-firefox-+-4*[{Analysis Helper}]
        |         |-{Cache I/O}
        |         |-{Cache2 I/O}
        |         |-{Cert Verify}
        |         |-3*[{DOM Worker}]
        |         |-{Gecko_IOThread}
        |         |-{HTML5 Parser}
        |         |-{Hang Monitor}
        |         |-{Image Scaler}
        |         |-{JS GC Helper}
        |         |-{JS Watchdog}
        |         |-{Proxy R~olution}
        |         |-{Socket Thread}
        |         |-{Timer}
        |         |-{URL Classifier}
        |         |-{gmain}
        |         |-{localStorage DB}
        |         |-{mozStorage #1}
        |         |-{mozStorage #2}
        |         |-{mozStorage #3}
        |         |-{mozStorage #4}
        |         `-{mozStorage #5}
        |-gpg-agent
        |-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
        |                               |          `-{Xorg.bin}
        |                               `-dwm-+-dwmstatus
        |                                     `-xterm---bash-+-bash
        |                                                    `-pstree
        |-systemd---(sd-pam)
        |-systemd-journal
        |-systemd-logind
        |-systemd-udevd
        |-wpa_actiond
        `-wpa_supplicant

Update 2: I guess the question can also be boiled down to: What should be the parent of a process? Should it e.g. be a shell or should it be the init process i.e. the process with PID 1?

share|improve this question
1  
The terse answer to your question would be "whatever gets the results you want." –  Wayne Werner Aug 27 at 2:12
1  
dang, garbage - you ask some good questions. but I think wayne's on the nose here - your latest edit asks about init - to which the answer might be... maybe? it depends on how/if you plan to talk to it, what init you use, and where the data channels are. In general that stuff will tend to work itself out - that's what init is for. In any case, usually when you daemonize a process then init. Or if you want job control, current shell. –  mikeserv Aug 27 at 2:29
    
Hahaha, cheers @mikeserv; 4:37 am in the morning here and already the first laugh of the day. True, that stuff always somehow works out. I will remove dmenu and see how I get along with what I learned. I find exec /path/to/Program & exit or /bin/bash -c /path/to/Program & exit to be quite usable. But they all make 1 i.e. init the parent of the Program which is fine with me as long as this makes sense and does not violate any basic *nix principles. –  brauner Aug 27 at 2:36
    
@lord.garbage - that's because you exec &, I think. I usually just do my stuff from the terminal... maybe you'd get some use out of ben crowell's question here. I have an answer there, but all of them are very good. anyway, when you background a process and its parent dies like: sh -c 'cat & kill $$' you orphan it, and it winds up getting reaped eventually. that's init's job - that's why they all fall to it. –  mikeserv Aug 27 at 2:44
    
Maybe a simpler question for now is: How is it possible to get the above process tree from the shell: systemd--bash--chromium. All methods I try will ultimately lead to a process tree of the following form systemd--chromium when I spawn firefox from the shell. How is the shell demonized here? It is not associated with any terminal. –  brauner Aug 27 at 13:30

1 Answer 1

up vote 4 down vote accepted

Well, you seem to have a pretty good understanding of it.  To clarify some of what you have,

  • sh -c /path/to/Program is fairly similar to

    $ sh
    % /path/to/Program
    % Ctrl+D                             (or you could type “exit”)
    $ 

    where you start a new shell process, provide the application command path to the new shell, and then let the new shell terminate.  I have shown the new shell giving a different prompt for illustration purposes; this probably wouldn’t happen in real life.  The sh -c "command" construct is mostly useful for doing tricky stuff, like wrapping multiple commands into a bundle, so they look like a single command (sort of a single-use unnamed script), or building complicated commands, possibly from shell variables.  You would hardly ever use it just for running a single program with simple argument(s).

  • 2>&1 means redirect the standard error to the standard output. This doesn’t really have much to do with &; rather, you use it when a command sends error messages to the screen even if you say command > file and you want to capture the error messages in the file.
  • Redirecting output to nohup.out is a trivial side-effect of nohup.  The primary purpose of nohup command & is to run command asynchronously (commonly known as “in the background”, or as a “shell independent process”, to use your words) and configure it so it has a better chance of being able to continue to run if you terminate the shell (e.g., logout) while the command is still running.

bash(1) and the Bash Reference Manual are good sources of information.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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