Tek bir borulu komut için kanal hatası ayarlama


19

Ben böyle olmayan bir BASH komut dosyasından (yani PHP komut dosyası) borulu kabuk komutları bir dizi yürütmek gerekir:

command1 | command2 | command3

böylece, command1sıfırdan farklı bir çıkış koduyla başarısız olursa, diğer komutlar da başarısız olur. Şimdiye kadar bulduğum şey:

set -o pipefail && command1 | command2 | command3

Ancak terminalden iyi çalışsa bile, komut dosyasından yürütüldüğünde bunu üretir:

sh: 1: set: Geçersiz seçenek -o pipo hatası


Anlaşılmaktadır /bin/shsevmez set -o pipefail. Aslında bashkılık değiştirmiş mi, yoksa farklı bir kabuk mu? Ne zaman bashçalıştırılır /bin/sh, kabul eder set -o pipefailmi?
Jonathan Leffler

@JonathanLeffler Koştuğumda /bin/sh set -o pipefaildiyor ki /bin/sh: 0: Can't open set(ile aynı şey sudo). Umarım doğru test ettim. Sistem Ubuntu 12'dir.
Desmond Hume

Denemeniz gerekecek /bin/sh -c "set -o pipefail"; olduğu gibi, kabuk denilen geçerli dizinde bir komut dosyası yürütmeye çalışıyordu setve onu bulamadı.
Jonathan Leffler

@JonathanLeffler /bin/sh -c "set -o pipefail"çalışmıyor, ancak çalışıyor bash -c "set -o pipefail".
Desmond Hume

Yani, probleminiz komut dosyasının /bin/shtanımadığı tarafından çalıştırılmasıdır set -o pipefail. Sonuç olarak, komut dosyasının /bin/bashyerine çalıştırıldığından emin olmanız gerekir /bin/sh. Ya da kendinize güveniyorsanız, şu anda bağlı olduğu kabuk veya bir kopya yerine , cesur ve muhtemelen aptalca /bin/shbir bağlantı /bin/bashveya kopya olarak değiştirin. Bunun olduğundan eminseniz, /bin/shşu şekilde çalıştırıldığında ortaya çıkmayan bashdavranışlar kullanırsınız ; kullanmak olarak . bash/bin/shbashbash
Jonathan Leffler

Yanıtlar:


18

Bash komut satırından, pipefaildaha sonra ayarlanmamak için bir alt kabuk çağırmanız gerekir :

$ (set -o pipefail && command1 | command2 | command3)

Bu, pipefailseçeneğin etkisini parantez tarafından oluşturulan alt kabukla sınırlar (...).

Gerçek bir örnek:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

-cSeçeneği olan açık bir kabuk çağrısı kullanırsanız, aşağıdakileri yapmak bashiçin bir shtakma adla veya takma adla alt kabuğa ihtiyacınız yoktur bash:

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

Sizin seçeneği shkabul etmediği için pipefail, bunun eski veya değiştirilmiş bir sürümü basholduğunu veya aslında başka bir kabuk olduğunu varsaymak zorundayım .


1
$İlk parçada komutun bir parçası mı sadece bir kabuk istemi? Her iki şekilde de denedim, gerçekten işe yaramadı. bash -cYol her zaman değil çok şık tho çalışır ..
Desmond Hume

6

Neden yukarıda belirtilmediğinden emin değilim, ancak pipefailkullanarak açıkça ayar yapmak mümkündür set +o pipefail.

set -o pipefail
command1 | command2 | command3
set +o pipefail

Bir parçayı yürütüyorsanız ve pipefailönceden ayarlanmış olduğundan emin değilseniz, bunu daha önce önerildiği gibi alt kabukla kullanabilirsiniz:

# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )

0

$ (Command1) ile $? :

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

"Abc" yazdırır

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

"" Yazdırır.

"[$? -eq 0] &&", aşağıdaki komutun yalnızca bir öncekinin başarılı olması durumunda yürütüldüğü anlamına gelir.

Bu soruya cevap vermiyor, ama bu senin sorununun bir çözümü.


Komutların her birinin çıktısını her zaman bir değişkene kaydetmem gerektiği anlamına mı geliyor?
Desmond Hume

Her zaman bilmiyorum ama benim çözümümle evet (bir sonraki komutunuz için ihtiyacınız varsa). command1 && command2 && command3
Yazmadığı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.