이 질문을 정확하게 표현하기는 어렵지만 최선을 다하겠습니다. 나는 그것을 dwm
기본 창 관리자와 dmenu
응용 프로그램 실행 프로그램으로 사용합니다. 나는 브라우저 이외의 GUI 애플리케이션을 거의 사용하지 않습니다. 내 작업의 대부분은 명령줄에서 직접 수행됩니다. 또한 저는 운영 체제, 앱 등에서 미니멀리즘을 좋아합니다. 제가 절대로 제거하지 않는 도구 중 하나는 앱 실행기입니다. 주로 앱 런처의 작동 방식/무엇을 수행하는지에 대한 정확한 이해가 부족하기 때문입니다. 인터넷을 열심히 검색해봐도 모호한 설명밖에 나오지 않습니다. 내가 하고 싶은 것은 실제로 앱을 만드는 것 외에는 전혀 쓸모가 없기 때문에 앱 런처를 없애는 것입니다. 이를 위해 쉘에서 애플리케이션을 "제대로" 실행하는 방법을 알고 싶습니다. "올바른"의 의미는 "응용 프로그램 실행 프로그램이 하는 것처럼"으로 근사화될 수 있습니다. 나는 앱 실행 프로그램에 대해 충분히 알지 못하기 때문에 모든 앱 실행 프로그램이 동일한 방식으로 작동한다고 주장하지 않습니다.
나는 쉘에서 프로세스를 생성하는 다음 방법을 알고 있습니다.
exec /path/to/Program
새 프로세스를 생성하지 않고 쉘을 지정된 명령으로 교체sh -c /path/to/Program
쉘 관련 프로세스 시작/path/to/Program
쉘 관련 프로세스 시작/path/to/Program 2>&1 &
쉘 독립 프로세스 시작nohup /path/to/Program &
쉘 독립 실행형 프로세스를 시작하고 출력을 다음으로 리디렉션합니다.nohup.out
업데이트 1: 다른 조건에서 dmenu
반복 호출을 통해 다시 생성하는 등의 작업을 설명할 수 있습니다. ps -efl
이는 새로운 쉘을 생성 /bin/bash
하고 해당 쉘의 하위 애플리케이션 역할을 합니다 /path/to/Program
. 아이가 주변에 있는 한 껍질은 항상 주변에 있을 것입니다. (이것을 관리하는 방법은 제 능력이 아닙니다...) 대신 nohup /path/to/Program &
쉘에서 실행 하면 /bin/bash
프로그램은 해당 쉘의 하위 프로세스가 되지만 해당 쉘을 종료하면 프로그램의 상위 프로세스는 최상위 프로세스가 됩니다. 따라서 첫 번째 프로세스가 /sbin/init verbose
이미 존재하는 경우 PPID 1
해당 프로그램의 상위 프로세스가 됩니다. 다이어그램을 사용하여 설명하려는 내용은 다음과 같습니다. chromium
시작하기 dmenu
, firefox
시작하기 사용하기 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
업데이트 2: 이 질문은 다음과 같은 질문으로 귀결됩니다. 프로세스의 부모는 무엇이어야 합니까? 예를 들어, 쉘이어야 할까요, 아니면 프로세스여야 init
할까요 PID 1
?
답변1
프로그램을 실행하고 터미널에서 분리하는 방법에는 여러 가지가 있습니다. 하나는 백그라운드에서 실행하는 것입니다.서브쉘, 다음과 같이( firefox
좋아하는 프로그램으로 교체):
(firefox &)
다른 하나는 프로세스를 거부하는 것입니다.
firefox & disown firefox
애플리케이션 런처 작동 방식이 궁금하신 경우 dmenu
바이너리 1개와 셸 스크립트 2개( dmenu
, , dmenu_path
) 를 제공해 주세요 dmenu_run
.
dmenu_run
의 출력을 dmenu_path
dmenu로 파이프하면 $SHELL
설정한 변수로 파이프됩니다. 비어 있으면 사용됩니다 /bin/sh
.
#!/bin/sh
dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
dmenu_path
약간 복잡하지만 간단히 말해서 $PATH
환경 변수에 바이너리 목록을 제공하고 가능한 경우 캐싱을 사용합니다.
#!/bin/sh
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then
cache=$cachedir/dmenu_run
else
cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~
fi
IFS=:
if stest -dqr -n "$cache" $PATH; then
stest -flx $PATH | sort -u | tee "$cache"
else
cat "$cache"
fi
프로그램을 쉘에서 실행할 필요는 없습니다. 셸에 연결하지 않고 작성하는 또 다른 방법은 다음 dmenu_run
과 같습니다.
#!/bin/sh
$(dmenu_path | dmenu "$@") &
답변2
나는 G-Man의 답변을 정말 좋아합니다. 하지만 귀하의 우려가 혼란스러울 것 같아 답변을 드립니다. Wayne이 지적했듯이 가장 좋은 대답은 "원하는 결과를 얻는 것이 무엇이든"입니다.
Unix 프로세스 관리에서 각 프로세스에는 상위 프로세스가 있습니다. 유일한 예외는 init
시작 시 운영 체제에 의해 시작되는 프로세스입니다. 부모 프로세스가 종료될 때 모든 자식 프로세스를 가져가는 것은 정상적인 동작입니다. 이는 모든 하위 프로세스에 SIGHUP 신호를 전송하여 수행됩니다. SIGHUP의 기본 처리는 프로세스를 종료합니다.
사용자 프로세스에 대한 쉘 생성은 작성한 코드와 다르지 않습니다.포크(2)/실행(3)원하는 언어로 전화하세요. 셸은 상위 프로세스이며, 셸이 종료되면(예: 로그아웃) 생성된 하위 프로세스도 마찬가지입니다. 설명하는 미묘한 차이점은 해당 동작을 수정하는 방법일 뿐입니다.
exec /path/to/program
전화를 거는 것처럼실행(3). 예, program
상위 실행 쉘을 유지하면서 쉘을 으로 대체합니다 .
sh -c /path/to/program
.program
/path/to/program
( sh /path/to/script.sh
하위 쉘에서 실행 권한이 부족한 쉘 스크립트를 실행하는 데 사용할 수 있음)
/path/to/program
"포그라운드" 프로세스를 생성합니다. 즉, 쉘은 다른 작업을 수행하기 전에 프로세스가 완료될 때까지 기다립니다. 시스템 호출 컨텍스트에서는 다음과 같습니다.포크(2)/실행(3)/프로세스를 기다리는 중(2). 하위 프로세스는 상위 프로세스로부터 stdin/stdout/stderr을 상속받습니다.
/path/to/program &
(리디렉션 무시) "백그라운드 프로세스"를 만듭니다. 프로세스는 여전히 셸의 하위 프로세스이지만 상위 프로세스는 프로세스가 종료될 때까지 기다리지 않습니다.
nohup /path/to/program
옮기다노스햅(1)program
제어 터미널이 닫혀 있으면 SIGHUP이 전송되지 않도록 합니다. 전경 또는 배경 중 하나는 옵션입니다(대부분 프로세스가 배경에 있음에도 불구하고). nohup.out
다른 방식으로 표준 출력을 리디렉션하지 않으면 이는 단지 출력일 뿐입니다.
프로세스를 백그라운드에 넣을 때 상위 프로세스가 종료되면 두 가지 중 하나가 발생합니다. 부모라면제어 터미널, 그러면 SIGHUP이 어린이에게 전송됩니다. 그렇지 않은 경우 프로세스는 "고아"가 되어 init
프로세스에 의해 상속될 수 있습니다.
입력/출력/오류를 리디렉션할 때 각 프로세스가 소유한 파일 설명자를 상위 프로세스에서 상속된 파일이 아닌 다른 파일에 연결하기만 하면 됩니다. 이 중 어느 것도 프로세스 소유권이나 트리 깊이에 영향을 미치지 않습니다(그러나 3개 프로세스 모두를 터미널에서 백그라운드 프로세스로 리디렉션하는 것은 항상 의미가 있습니다).
하지만 프로세스 관리와 관련된 특정 문제를 해결하지 않는 한 쉘, 서브쉘 또는 하위 프로세스의 프로세스 생성에 신경써서는 안 된다고 생각합니다.
답변3
글쎄요, 당신은 이 점을 잘 이해하고 있는 것 같습니다. 당신이 가지고 있는 것 중 일부를 명확히 하기 위해,
sh -c /path/to/Program
매우 유사하다$쉿 %/경로/대상/프로그램 %Ctrl+D (또는 "출구") $
그 안에서 새 셸 프로세스를 시작하고, 새 셸의 응용 프로그램 명령 경로를 제공하고, 새 셸이 종료되도록 합니다. 설명을 위해 새 셸이 다른 프롬프트를 제공한다는 점을 보여 드렸습니다. 이는 실제 생활에서는 발생하지 않을 수 있습니다. 이 구조는 여러 명령을 단일 명령처럼 보이도록 패키지로 래핑하거나(이름이 지정되지 않은 일회성 스크립트와 유사) 쉘 변수에서 복잡한 명령을 작성하는 등 까다로운 작업을 수행하는 데 가장 유용합니다. 간단한 매개변수를 사용하여 단일 프로그램을 실행하는 데에는 거의 사용하지 않을 것입니다.
sh -c "command"
2>&1
표준 오류를 표준 출력으로 리디렉션합니다. 이는 별로 중요하지 않습니다&
. 대신 명령이 화면에 오류 메시지를 보낼 때 파일에 오류 메시지를 캡처하고 싶어도 사용할 수 있습니다.command > file
- 출력
nohup.out
을nohup
. 주요 목적은 비동기식으로 실행하고(종종 "백그라운드에서", 즉 "셸 독립 프로세스"라고 함) 실행하는 경우 계속 실행할 수 있는 가능성이 더 높도록 구성하는 것입니다. 명령이 여전히 실행 중인 동안(예: 로그아웃) 쉘을 종료합니다.nohup command &
command