Tam yolu belirtmeden Bash yerleşik yerine sistem komutunu kullan


17

Bash'i etkileşimli kabuğum olarak kullanıyorum ve her ikisinin de aynı adı paylaşması durumunda Bash'in bir kabuk yerleşik komutu yerine bir sistem komutu çalıştırmasını sağlamanın kolay bir yolu olup olmadığını merak ediyordum.

Örneğin, sinyal göndermek yerine adlandırılmış işlemlerin işlem kimliğini (pid) yazdırmak için sistemi kill(from util-linux) kullanın:

$ /bin/kill -p httpd
2617
...

Sistem komutunun tam yolunu belirtmeden, sistem komutu yerine Bash yerleşik kullanılır. killBuiltin yok -pkomut başarısız böylece seçeneği:

$ kill -p httpd
bash: kill: p: invalid signal specification

Bash'i kabuk yerine yerleşik harici `time` komutunu kullan bölümünde listelenen cevapları denedim, ancak çoğu sadece timebir kabuk anahtar kelimesi olduğu için çalışıyor - bir kabuk yerleşimi değil .

Bash yerleşkesini geçici olarak devre dışı bırakmak dışında enable -n kill, şimdiye kadar gördüğüm en iyi çözüm kullanmaktır:

$(which kill) -p httpd

Kabuk yerleşik yerine harici komut yürütmenin daha kolay (daha az yazmayı içeren) yolları var mı?

Bu killsadece bir örnek olduğunu ve yerleşik ile önek ile harici bir komutla aynı ada sahip işlevleri çalışmasını engeller gibi genelleştirilmiş bir çözüm istiyorum unutmayın command. Çoğu durumda, genellikle yerleşik sürümü kullanmayı tercih ederim, çünkü yeni bir işlem istemeyi kurtarır ve bazen yerleşik komutun harici komutun sahip olmadığı özelliklere sahiptir.


Geri çemberleri which killiçine almak (bunları yorumlara koyamazsınız) biraz daha kısadır.
abligh

@abligh İyi nokta. Komut yerine koymak için "yeni" er sözdizimini kullanmak için kendimi yıllarca harcadım. :)
Anthony G - Monica için adalet

@abligh: FYI, ters eğik çizgi (\) ile başlayarak yorumlara “backticks” koyabilirsiniz. Ama sopa ile nedenler vardır $(…)- bakınız bu , bu ve bu .
G-Man, 'Monica'yı Yeniden Başlat' diyor

Yanıtlar:


20

Yolunuzda envolduğunu varsayalım :

env kill -p http

envdeğiştirilmiş bir ortamda ilk argümanı tarafından adlandırılan yürütülebilir dosyayı çalıştırır; bu nedenle, kabuk yerleşik komutlarını bilmez veya bunlarla çalışmaz.

Bu, bazı kabuk işi kontrol hamlesi üretir, ancak harici bir komuta dayanmaz:

exec kill -p bash &

execgeçerli kabuğu değiştirmek için yürütülebilir bir dosya gerektirdiğinden, yerleşik öğeler kullanmaz. İş arka planda çalıştırılır, böylece çatallı arka plan kabuğunu değiştirirsiniz, geçerli kabuğunuzu değil.


2
envaçıkça doğru cevap IMHO.
abligh

@abligh: Silinen cevabımda yorum yapmakta haklısın. command -p cmdharici komut çağırıyor zsh, değil bash.
cuonglm

6
(exec kill -p http)işin şu anki kabuğunuz yerine bir alt kabuğun yerini almasına neden olur ve iş denetimini ele almak zorunda kalmazsınız.
Michael Hoffman

1
@AnthonyGeoghegan Gerçekten de, aynı envzamanda kabuk yapıları hakkında da bir şey bilmiyor, çünkü bu bir kabuk değil. Aynı etkiyi niceveya xargsbunun gibi başka bir programı elde edersiniz .
user253751

1

İstediğinizi yapmanın en basit yolu satırı koymak olabilir

alias kill="/bin/kill"

içine yerleştirin ~/.bashrc. Bundan sonra, her yeni giriş / bash çağrısı "öldürme" olarak yorumlanacaktır /bin/kill.


Zaten bir takma ad düşündüm ve bağlantılı olduğum soruda listelenen çözümlerden biriydi ama commandher "gölgeli" komut için ayrı bir takma ad oluşturmak yerine daha genel bir çözüm (çözüme benzer ) umuyorum . Şimdi bu soruyu daha açık ve net yapmak için düzenledim. Çoğu durumda, işlemler iş kimlikleriyle belirtilebildiğinden yerleşik sürümü kullanmayı tercih ederim. Yine de teşekkürler.
Anthony G - Monica için adalet

1

Biraz yazım gerektiren bir çözüm biliyorsanız ve daha az yazmayı gerektiren bir çözüm istiyorsanız, bunu oluşturun:

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

Normalde biraz çaba gerektiren şeylerin kısaltılması, bilgisayarların mükemmel olduğu şeydir.


1
Bu iyi bir genel nokta, bu yüzden cevabınızı onaylayacağım. Son birkaç yıldır, düzenli olarak kullandığım sistemler için bir takma ad, işlev ve komut dosyası koleksiyonu oluşturdum. Ancak, bazen yeni kurulumlar veya kurulum yapmadığım sunucular üzerinde çalışmak zorunda olduğum için, mümkün olduğunca özelleştirilmiş olmayan çözümler kullanmayı tercih ederim. Teşekkürler.
Anthony G - Monica için adalet

1

Bu çok özel durumda, komut pgrepihtiyaca tam olarak uyar.

Genel anlamda bir işlev çalışır. "Dosya komutu" ndan:

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

olarak ara

fcmd kill -p httpd

Ancak daha az yazmaya ihtiyacınız varsa, iyi bir takma addan daha kısa bir yol yoktur.

"Liste pid" (lp) kavramından:

alias lp='/bin/kill -p'

sonra şunu yazın:

lp httpd

0

(Zsh olarak) Sistem sürümünü almak için herhangi bir komut adını önek olarak = işareti ile ekleyebilirsiniz. Bu aynı zamanda belirli bir senaryoyu bozan diğer takma adlardan kaçınmanın kullanışlı bir yoludur.

$ =kill -p httpd

1
Bash 4.3.30 sürümü ile denedim ve işe yaramadı. Daha önce hiç böyle bir sözdizimi görmedim; bu özelliğin belgelendiği yere bir bağlantı ekleyebilir misiniz? Normalde bir komutun takma adı olmayan sürümünü çalıştırmak için ters eğik çizgiyle bir takma ad önekini eklerdim.
Anthony G - Monica için adalet

@ Anthony belki bu zshtek şeydir. Düzenli kullanıyorum ama bashyarın bilgisayardan kontrol edeceğim .
Caleb

Aşina olmadığım bir kabuk olabileceğinden şüphelendim (sadece bash, dash ve csh'a aşinayım). Yalnızca işe yarayan başka bir yanıt (silindiğinden beri) vardı zsh. Bu soruyu etiketli bashve başlığında kullandım, ancak bir zsh kullanıcısı hala yararlı bulacağı için bu cevabı saklamalısınız.
Anthony G - Monica için adalet

-1

Manpage'inize karşı bir hata raporu gönderebilir killve bunun neden alınan standart dışı seçenekleri içerdiğini ve özellikleri almak istediğinizde pkillkullandığınızı sorabilirsinizpkillpkill.

Eğer ararsanız:

pkill httpd

tarif ettiğiniz problemlerden kaçınırsınız.

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.