Linux kabuk betiği: Bir programı yalnızca varsa çalıştırın, yoksa yoksayın


15

Bir programlama am Linux shell script uygun aracı, diyelim yalnızca yürütme sırasında durum afişler yazdırır figlet, bir kurulu (: Sistem ulaşılabilir budur yolu ).

Misal:

#!/usr/bin/env bash
echo "foo"
figlet "Starting"
echo "moo"
figlet "Working"
echo "foo moo"
figlet "Finished"

İşten benim komut dosyası için istiyorum hatasız bile figletedilir yüklü değil .

Pratik bir yöntem ne olabilir ?



@sudodus: 'figlet' (ve parametreleri) komutunu göz ardı etmek sorun olmayacaktır. Elbette idam devam ediyor.
Sopalajo de Arrierez

2
Bu sorunun başlığı beni her türlü metafizik problemde buldu
g_uint

2
Tüm hataları yoksaymak istiyor musunuz ? Sadece kullan figlet ... || true.
Giacomo Alzetta

Çıkış kodlarını umursamıyorsanız, bir kısayol kullanmaktır figlet || true, ancak sizin durumunuzda düz metin içeren bir kabuk işlevi muhtemelen hiçbir Afiş yazdırılamıyorsa istediğiniz şeydir.
Eckes

Yanıtlar:


30

Yorumum, araçla aynı adlı bir sarmalayıcı işlevi kullanır; bu işlevde, varsa gerçek aracı yürütün:

figlet() {
  command -v figlet >/dev/null && command figlet "$@"
}

O zaman figlet arg1 arg2...senaryonuzda değişmemiş olabilirsiniz .

@Olorin daha basit bir yöntem buldu: yalnızca ihtiyacımız olduğunda bir sarmalayıcı işlevi tanımlayın (araç yoksa):

if ! command -v figlet > /dev/null; then figlet() { :; }; fi

figletFigür yüklü olmasa bile argümanların yazdırılmasını istiyorsanız, Olorin'in önerisini aşağıdaki gibi ayarlayın:

if ! command -v figlet > /dev/null; then figlet() { printf '%s\n' "$*"; }; fi

1
Nereden commandgeliyor? Kurulumlarımda yok (Red Hat 6.8 Enterprise ve Cygwin64).
eewanco

1
@ eewanco, bkz. unix.stackexchange.com/a/85250/117549 ; Uzun lafın kısası, muhtemelen kabuğunuz olan bash üzerine inşa edilmiştir.
Jeff Schaller

4
commandbir POSIX Bourne kabuğu yerleşkesidir. Normalde sağlanan komutu yürütür, ancak -vbayrak daha typebaşka bir kabuk yerleşik gibi davranmasını sağlar .
wyrm

@eewanco type -a commandsize gösterecek. whicholacak sadece sizin üzerinde yürütülebilir göstermek $PATHdeğil, yerleşik ins, anahtar kelimeler işlevler veya takma ad.
l0b0

@ l0b0: bash ve varsayılan profil (ler) ile RedHat-aileye which gelmez bu takma adlar, çünkü uygulanabilir bir takma ad bulmak whichçalıştırmak için kendisini /usr/bin/which(!) ve boru içeri görünüme kabuğun diğer adları listesi (Tabii \whichtakma bastırır ve yalnızca takma adları göstermeyen programı kullanır.)
dave_thompson_085

14

Var olup figletolmadığını görmek için test edebilirsiniz

if type figlet >/dev/null 2>&1
then
    echo Figlet is installed
fi

6

Bunu yapmanın yaygın bir yolu test -xaka [ -x. İşte /etc/init.d/ntpbir Linux sisteminden alınan bir örnek :

if [ -x /usr/bin/lockfile-create ]; then
    lockfile-create $LOCKFILE
    lockfile-touch $LOCKFILE &
    LOCKTOUCHPID="$!"
fi

Bu varyant, yürütülebilir dosyanın tam yolunu bilmeye dayanır. In /bin/lesspipeI birleştirerek o etrafında çalışan bir örnek bulundu -xve whichkomut:

if [ -x "`which bunzip`" ]; then bunzip -c "$1"
else echo "No bunzip available"; fi ;;

Bu şekilde PATH, bunzipyürütülebilir dosyanın nerede olduğunu önceden bilmeden çalışacaktır .


4
Kullanmawhich . Hatta eğer whichçalıştı kullanarak test -xkendi çıkışında saçma: Eğer bir yol alırsanız which, onun var.
Gilles 'SO- kötü olmayı bırak'

1
@Gilles: Teknik olarak konuşursak, test -xbir dosyanın var olup olmadığını kontrol etmekten daha fazlasını yapar test -e. Ayrıca dosyanın yürütme izinlerinin ayarlanıp ayarlanmadığını da denetler.
comfreak

@comfreak Öyle which.
Gilles 'SO- kötü olmayı bırak

5

Komut dosyanızın başlangıcında, figletvar olup olmadığını kontrol edin ve yoksa, hiçbir şey yapmayan bir kabuk işlevi tanımlayın:

type figlet >/dev/null 2>&1 || figlet() { :; }

typefigletkabuk yerleşik, işlev, takma ad veya anahtar sözcük olarak var olup olmadığını denetler , >/dev/null 2>&1stdin ve stdout'u atar , böylece çıktı almazsınız ve yoksa , hiçbir şey yapmayan bir işlev olarak figlet() { :; }tanımlar figlet.

Bu şekilde, komut dosyanızın her satırını düzenlemeniz figletveya her figletçağrıldığında var olup olmadığını kontrol etmeniz gerekmez .

İsterseniz bir teşhis mesajı ekleyebilirsiniz:

type figlet >/dev/null 2>&1 || { echo 'figlet not installed.' ; figlet() { :; } ; }

Bonus olarak, hangi kabuğu kullandığınızdan bahsetmediğiniz için, bunun POSIX uyumlu olduğuna inanıyorum, bu yüzden çoğu kabukta çalışması gerekir.


Bu cevabın basitliğini seviyorum. Ayrıca bash kullanıyorsanız type figlet >/dev/null 2>&1ile değiştirebilirsiniz hash figlet 2>/dev/null. (OP, "PATH'ımdaysa" dedi.)
Joe

5

Başka bir alternatif - proje otomatik yapılandırma komut dosyalarında gördüğüm bir desen:

if [ -x /usr/bin/figlet ]
then
    FIGLET=/usr/bin/figlet
else
    FIGLET=:
fi

$FIGLET "Hello, world!"

Sizin özel durumunuzda bile,

if [ -x /usr/bin/figlet ]
then
   SAY=/usr/bin/figlet
elif [ -x /usr/local/bin/figlet ]
then
   SAY=/usr/local/bin/figlet
elif [ -x /usr/bin/banner ]
then
   SAY=/usr/bin/banner
else
   SAY=/usr/bin/echo
fi

$SAY "Hello, world!"

Belirli bir yolu bilmiyorsanız, elifbilinen konumları denemek için birden fazla (yukarıya bakın) deneyebilir veya yalnızca PATHkomutu her zaman çözmek için kullanabilirsiniz :

if command -v figlet >/dev/null
then
    SAY=figlet
elif command -v banner >/dev/null
then
    SAY=banner
else
    SAY=echo
fi

Genel olarak, komut dosyaları yazarken, yalnızca benim belirlediğim belirli konumlardaki komutları çağırmayı tercih ederim. Son kullanıcının PATH, belki de kendi başına neler getirebileceğinin belirsizliğini / riskini sevmiyorum ~/bin.

Örneğin, aradığım belirli bir komutun çıktısına göre dosyaları kaldırabilecek başkaları için karmaşık bir komut dosyası yazıyordum, yanlışlıkla ~/binkomutlarında olabilecek veya olmayabilecek bir şey almak istemezdim Tahmin etmiştim.


3
Ya figletoldu /usr/local/binya /home/bob/stuff/programs/executable/figlet?
Gilles 'SO- kötü olmayı bırak'

3
type -p figlet > /dev/null && figlet "foo"

Bash typekomutu bir komut, işlev, takma ad, anahtar kelime veya yerleşik (bulur) bulur help typeve konumu veya tanımı yazdırır. Ayrıca, aramanın sonucunu temsil eden bir dönüş kodu döndürür; bulunursa true (0). Burada yaptığımız şey figletyolu bulmaya çalışmaktır ( -psadece dosyaları aramak, yerleşik veya işlevleri değil, aynı zamanda hata mesajlarını bastırmak anlamına gelir), çıktıyı atmak (işte budur > /dev/null) ve true değerini döndürürse ( &&) , yürütür figlet.

figletSabit bir konumdaysa bu daha basittir :

[ -x /usr/bin/figlet ] && /usr/bin/figlet "foo"

Burada çalıştırılabilir ( ) olup olmadığını ve (eğer ) çalıştırıp yürütmediğini görmek için test(aka [) komutunu kullanıyoruz . Bu çözüm, kullandığımdan daha portatif olduğunu düşünüyorum./usr/bin/figlet-x&&type

Bunu sizin için yapan bir işlev yapabilirsiniz:

function x() {
    if type -p "$1" >/dev/null; then
        cmd="$1"
        shift
        "$cmd" "$@"
    fi
}

(Potansiyel alanlar nedeniyle teklifler gereklidir)

Sonra sadece yapardınız:

x figlet "foo"

0

o /, şöyle bir şey söylerdim

#!/usr/bin/env bash
# if figlet is installed :
if [ "$(which figlet 2>/dev/null)" ]; then
       # do what you wanted to do
       echo "foo"
       figlet "Starting"
       echo "moo"
       figlet "Working"
       echo "foo moo"
       figlet "Finished"
# if not
else
       # exit program with an error
       echo "please install figlet"
       exit 1
fi

0

Herhangi bir çıktıyı bastırarak bir test yürütmesi yapabilir ve başarı / başarısızlık kodunu test edebilirsiniz. Bu testi ucuz yapmak için figüran argümanları seçin. -? veya --help veya --version bariz olasılıklardır.

if figlet --help >/dev/null 2>&1 ; then
    # figlet is available
    echo "foo"
    figlet "starting"
    #etc
else
    rc=$?
    echo "figlet is not installed or not working correctly (return code ${rc})"
fi

Aşağıdaki yoruma yanıt olarak eklendi: Bu şeklin var olduğunu gerçekten test etmek istiyorsanız, kullanılabilir olmadığını değil,

figlet --help >/dev/null 2>&1 
rc=$?
if [ $rc -eq 127 ] ; then # 127 is "command not found" on linux bash 4.4.23(1)
    echo "command figlet not found"
else
    figlet "whatever" # use figlet
fi

Buradaki problem, figlet'in kurulmamasının yanı sıra başarısız olabileceğidir, bu nedenle sadece çıkış kodunu test etmek yeterli değildir.
Chris

Gerçekten sadece kurulumu için test etmek istiyorsanız $?, 127'ye (linux sistemimde) eşit olup olmadığını test etmek istersiniz . 127 "komut bulunamadı". Ama benim düşüncem, rasyonel komutlar için, eğer command --helpbaşarısız olursa, o zaman kurulumun orada olmayabileceği kadar yeterince tıkanmış olmasıdır!
nigel222

1
126 "komut bulundu ancak yürütülebilir değil", bu yüzden de buna karşı test etmek istersiniz. Maalesef, --helpmüsait olmaya bağlı olamazsınız . Posix yardımcı programlarına sahip değil, biri için ve posix yönergeleri aslında buna karşı öneriyor . örneğin, sistemimdeki çıkış durumuyla at --helpbaşarısız oluyor . at: invalid option -- '-'130
Chris

Ayrıca, elbette, eğer figlet 127 durumu ile çıkabiliyorsa, bu da bir sorun olabilir.
Chris

126 mantıklı nokta. Çoğu aklı başında hizmet programında ... gibi bir tür hafif zararsız komut seçeneği vardır -? --help --versionya da neyin figlet -0 --illegalçıktığını bulabilir ve bunu başarı göstergeniz olarak değerlendirebilirsiniz (127 olmadığı sürece, hangi sınıfta olacağım) sabotaj olarak).
nigel222
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.