Bir kabuktan bir uygulamayı “doğru şekilde” başlatma


21

Soruyu tam olarak ifade etmekte zorlanıyorum ama elimden geleni yapacağım. Kullandığım dwmvarsayılan pencere yöneticisi olarak vedmenubenim uygulama başlatıcı olarak. GUI uygulamalarını tarayıcım dışında neredeyse hiç kullanmıyorum. İşlerimin çoğu doğrudan komut satırından yapılır. Ayrıca, işletim sistemleri, uygulamalar vb. İle ilgili çok az bir minimalizm hayranıyım. Hiç kurtulamadığım araçlardan biri de bir uygulama başlatıcıydı. Temel olarak, uygulama başlatıcılarının nasıl çalıştığı / ne yaptıkları konusunda tam bir anlayışım olmadığı için. Kapsamlı internet araması bile sadece belirsiz bir açıklama gösterir. Yapmak istediğim şey, uygulama başlatıcıdan bile kurtulmaktır, çünkü aslında uygulamayı yumurtlama dışında, bunun için kesinlikle kullanmıyorum. Bunu yapmak için uygulamaları kabuktan "doğru şekilde" nasıl başlatacağımı bilmek istiyorum. "Doğru" ifadesinin anlamı "bir uygulama başlatıcısının yaptığı gibi" ile yakınlaştırılabilir.

İşlemleri kabuktan çıkarmanın aşağıdaki yollarını biliyorum:

  1. exec /path/to/Program yeni bir işlem oluşturmadan shell'i belirtilen komutla değiştir
  2. sh -c /path/to/Program kabuk bağımlı süreç başlatmak
  3. /path/to/Program kabuk bağımlı süreç başlatmak
  4. /path/to/Program 2>&1 & kabuktan bağımsız süreç başlat
  5. nohup /path/to/Program & Kabuktan bağımsız işlem başlatmak ve çıktıyı nohup.out

Güncelleme 1: Örneğin dmenu, tekrarlanan çağrılardan ps -eflfarklı koşullar altında neyin yeniden yapılandırıldığını gösterebilirim . Yeni bir kabuk ortaya çıkarır /bin/bashve bu kabuğun alt öğesi olarak uygulamayı oluşturur /path/to/Program. Çocuk etrafta olduğu sürece kabuk etrafta olacaktır. (Bu nasıl yönetir benden öte ...) Buna karşılık nohup /path/to/Program &, bir kabuktan çıkarırsanız /bin/bash, program bu kabuğun alt öğesi olur, ancak bu kabuktan çıkarsanız, programın üst öğesi en üst süreç olacaktır. Yani eğer ilk süreç örnekse /sbin/init verboseve varsa, PPID 1programın üst öğesi olacaktır. Burada bir grafik kullanarak açıklamaya çalıştı budur: chromiumaracılığıyla başlatılan dmenu, firefoxkullanılarak başlatıldı 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

Güncelleme 2: Sanırım soru şu şekilde de kaynatılabilir: Bir sürecin ebeveyni ne olmalı? Örneğin bir kabuk olmalı mı inityoksa süreç PID 1mi yani süreç mi?


3
Sorunuzun kısa yanıtı "istediğiniz sonuçları ne olursa olsun" olacaktır.
Wayne Werner

1
dang, çöp - bazı güzel sorular soruyorsun. ama bence wayne burunda - son düzenlemeniz soruyor init- cevabın hangisi olabileceğini ... belki? onunla nasıl / ne şekilde konuşmayı planladığınıza, ne initkullandığınıza ve veri kanallarının nerede olduğuna bağlıdır. Genel olarak, bu şeyler kendini çözme eğiliminde olacaktır - bunun initiçin budur. Her durumda, genellikle bir süreci arka plana ayırdığınızda init. Veya iş kontrolü, mevcut kabuk istiyorsanız.
mikeserv

Hahaha, şerefe @mikeserv; 4:37 sabah buradayım ve zaten günün ilk gülüşü. Doğru, bu şeyler her zaman bir şekilde işe yarıyor. dmenuÖğrendiklerimle nasıl geçineceğimi göreceğim. Ben bulmak exec /path/to/Program & exitveya /bin/bash -c /path/to/Program & exitoldukça kullanışlı olması. Ama hepsi marka 1yani initebeveyni Programsürece bu mantıklı ve tüm baz ihlal etmediği şekilde bana uyar *nixilkeleri.
lord.garbage

@ lord.garbage - çünkü sen exec &, sanırım. Genellikle eşyamı terminalden yapıyorum ... belki ben burada crow'ın sorusundan biraz faydalanırsın . Orada bir cevabım var, ama hepsi çok iyi. Her neyse, bir süreci arka planladığınızda ve üst öğesi şu şekilde ölürse: sh -c 'cat & kill $$'yetimsiniz ve sonunda biçilir. bu init'in işi - bu yüzden hepsi ona düşüyor.
mikeserv

Şimdilik belki daha basit bir soru: bu mümkün kabuğundan Yukarıdaki işlem ağacını nasıl alabilirsiniz? systemd--bash--chromium. Denediğim tüm yöntemler, systemd--chromiumfirefox'u kabuktan çıkardığımda sonuçta aşağıdaki formdaki bir işlem ağacına yol açacaktır . Kabuk burada nasıl şeytanlaştırılıyor? Herhangi bir terminal ile ilişkili değildir.
lord.garbage

Yanıtlar:


7

Bunu oldukça iyi anlıyor gibisin. Sahip olduklarınızdan bazılarını netleştirmek için,

  • sh -c /path/to/Program oldukça benzer

    $ sh 
    % / path / to / Program 
    % Ctrl+ D                             (veya “ exit yazabilirsiniz ) 
    $

    burada yeni bir kabuk işlemi başlattığınızda, yeni kabuğa uygulama komut yolunu sağlayın ve sonra yeni kabuğun sona ermesine izin verin. Yeni kabuğun gösterim amacıyla farklı bir komut istemi gösterdim; bu muhtemelen gerçek hayatta olmazdı. Yapı, bunlar (bir çeşit tek kullanımlık isimsiz yazısının) tek bir komut gibi görünen bu yüzden, bir demet şeklinde birden fazla komutları sarma gibi, zor şeyler yapmak için çok yararlıdır, ya da muhtemelen kabuk değişkenler, komutları karmaşık bina. Basit argüman (lar) ile tek bir program çalıştırmak için neredeyse hiç kullanmazsınız.sh -c "command"

  • 2>&1standart hatayı standart çıktıya yönlendirmek anlamına gelir. Bunun gerçekten bir ilgisi yok &; bunun yerine, bir komut söylediğinizde ve dosyadaki hata mesajlarını yakalamak istediğinizde bile ekrana hata mesajları gönderdiğinde kullanırsınız .command > file
  • Çıktının yönlendirilmesi nohup.outönemsiz bir yan etkidir nohup. Birincil amacı çalıştırmaktır uyumsuz (yaygın olarak bilinen “arka planda”, ya da bir sözlerinizi kullanmak, “bağımsız sürecini kabuk”) o edememek şansı daha vardır bu yüzden eğer çalışmaya devam etmek ve yapılandırmak bunu komut hala çalışırken kabuğu (örneğin, oturumu kapatma) sonlandırın.nohup command &command

bash(1)ve Bash Referans Kılavuzu iyi bilgi kaynaklarıdır.


7

Bir programı yürütmenin ve bir terminalden ayırmanın birkaç yolu vardır. Birincisi, bunu bir alt kabuğun arka planında çalıştırmaktır, bunun gibi ( firefoxen sevdiğiniz programla değiştirin ):

(firefox &)

Bir diğeri ise süreci reddetmektir:

firefox & disown firefox

Eğer uygulama rampaları iş, nasıl merak ediyorsanız dmenu: ikili 1 sağlamakta ve 2 kabuk komut dmenu, dmenu_pathve dmenu_runsırasıyla.

dmenu_runçıkışını dmenu_pathdmenü'ye dönüştürür, bu da $SHELLdeğişkeninizi ayarladığınız her şeye yönlendirir. Boşsa kullanacaktır /bin/sh.

#!/bin/sh
dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &

dmenu_pathbiraz daha karmaşıktır, ancak kısaca $PATHortam değişkeninizdeki ikili dosyaların bir listesini sağlar ve mümkünse bir önbellek kullanır.

#!/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

Programların kabuklarda çalıştırılması gerekmez. Bir dmenu_runkabuğa boru eklemeden yazmanın başka bir yolu :

#!/bin/sh
$(dmenu_path | dmenu "$@") &

6

G-Man'ın cevabını çok seviyorum. Ama cevap veriyorum çünkü bence endişeleri karıştırıyorsunuz. Wayne'in işaret ettiği gibi, en iyi cevap "istediğiniz sonuçları ne elde ederse edin" dir.

Unix işlem yönetiminde her işlemin bir üst öğesi vardır. Bunun tek istisnası init, işletim sistemi tarafından önyükleme sırasında başlatılan işlemdir. Bir üst sürecin tüm alt süreçlerini öldüğü zaman yanına alması normal bir davranıştır. Bu, SIGHUP sinyalini tüm alt süreçlere göndererek yapılır; SIGHUP'un varsayılan kullanımı işlemi sonlandırır.

Kullanıcı süreçlerinin kabuk doğurması, çatal (2) / exec (3) çağrılarını istediğiniz dilde kodlamanızdan farklı değildir. Kabuk ana babanızdır ve kabuk sona ererse (örn. Oturumu kapatırsanız), ortaya çıktığı alt süreç (ler) onunla birlikte gider. Açıkladığınız nüanslar bu davranışı değiştirmenin sadece yoludur.

exec /path/to/programexec (3) çağrısı gibidir . Evet, programhangi ebeveynin kabuğu başlattığını koruyarak kabuğunuzun yerini alacaktır .

sh -c /path/to/programtür anlamsızca bir alt süreç oluşturacak bir alt kabuk işlemi oluşturur program. /path/to/programYürütülebilir bir dosya değil, gerçekte bir komut dosyası komut dizisi ise değerlidir . ( sh /path/to/script.shalt kabukta yürütme izinleri olmayan bir kabuk komut dosyasını çalıştırmak için kullanılabilir)

/path/to/programbir "ön plan" işlemi yaratır, yani kabuk başka bir işlem yapmadan önce işlemin tamamlanmasını bekler. Sistem çağrısı bağlamında, fork (2) / exec (3) / waitpid (2) gibidir . Çocuğun ebeveyninden stdin / stdout / stderr'yi miras aldığını unutmayın.

/path/to/program &(yeniden yönlendirmeyi yoksayarak) bir "arka plan işlemi" oluşturur. İşlem hala kabuğun bir çocuğudur, ancak ebeveyn bunun sona ermesini beklemez.

nohup /path/to/programkontrol terminali kapalı ise SIGHUP'un gönderilmesini önlemek için nohup (1) çağırır program. Ön planda mı yoksa arka planda mı olduğu bir seçimdir (çoğunlukla işlem arka planda olmasına rağmen). Bunun nohup.outyalnızca stdout'u başka şekilde yönlendirmediğinizde çıktı olduğunu unutmayın.

Bir işlemi arka plana koyduğunuzda, üst süreç ölürse iki şeyden biri olur. Ebeveyn kontrol eden bir terminal ise SIGHUP çocuklara gönderilir. Değilse, işlem "yetim" olabilir ve initişlem tarafından devralınır .

Giriş / çıkış / hata yönlendirme yaptığınızda, her işlemin sahip olduğu dosya tanımlayıcılarını üst öğesinden devraldığından farklı dosyalara bağlarsınız. Bunların hiçbiri işlem sahipliğini veya ağaç derinliğini etkilemez (ancak arka plan işlemleri için 3'ün tamamını bir terminalden uzağa yönlendirmek her zaman mantıklıdır).

Tüm bunlarla birlikte, süreç yönetimi ile ilgili ele aldığınız belirli bir sorun olmadığı sürece, kabuk veya alt kabuklar veya alt süreçler tarafından süreç oluşturma ile ilgilenmeniz gerektiğini düşünmüyorum.


nitpick: sh -c /path/to/programyürütülebilir bitleri eksikse programı kabuk betiği olarak çalıştırmaz sh /path/to/program. sh -c /path/to/programbir kabuk açacak ve çalıştırılamazsa /path/to/programbu kabukta bir komut olarak çalışacaktır .
filbranden

Eh, eğer beceriksiz olursak, ikimiz de yanılıyoruz. sh -c /path/to/programkomutları /path/to/programkabuğa girdi olarak okur . Dosyanın yürütme iznine sahip olması gerekmez, ancak bir kabuk betiği olmalıdır
jwm

Hmmm, sh /path/to/programöyle. Sadece kendimi denedim:, echo echo hello world >abc.shsonra sh ./abc.shyazdırır hello world, sh -c ./abc.shderken sh: ./abc.sh: Permission denied(bu, ./abc.shmevcut kabukta doğrudan koşmanızla aynıdır .) Bir şey mi kaçırdım? (Ya da belki de önceki yorumda kendimi iyi ifade etmedim ...)
filbranden

Benim hatam. sh -c _something_Sadece yazarak aynıdır _something_alt kabuğun yumurtlama haricinde istemi emrinde. Bu nedenle, yürütme bitini (dosya olarak) kaçırırsanız başarısız olacağından emin olursunuz. Öte yandan, bir dizi kabuk komutu sağlayabilir sh -c "echo hello world"ve iyi çalışır. Bu nedenle, yazdıklarınızın yürütme bitine (veya hatta bir dosyaya) sahip olması gerekmez, yalnızca kabuk yorumlayıcı onunla bir şeyler yapabilir.
jwm

Ben OP bazı derlenmiş veya sistem çalıştırılabilir atıfta olduğuna inanıyorum, bu yüzden yürütme izni kabul.
jwm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.