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.