Zaman komutuna benzer şekilde komutun günlük çıkış kodunu girin


10

kullanma

time sleep 1

verim:

$ time sleep 1

real    0m1.005s
user    0m0.001s
sys     0m0.001s

çıkış kodunu yazdırmak için kullanabileceğim bir komut sleepveya çalıştırmak istediğim komut var mı?

Bir şey sever:

$ log-exit-code sleep 1

belki de bu yeterli?

sleep 1 && echo "$?"

3
Hayır, sleep 1 && echo $?uyuyan hücrenin kodunu yalnızca sıfır olduğunda yazdırır ...
Satō Katsura

oh lol haklısın
Alexander Mills

1
sleep 1 && echo "$?" || echo "$?"
jesse_b

2
Diğerleri orijinal imo değerini attığından bir cevap ekledim, imo kötüdür (bu cevaplardan sonra, $? Her zaman 0 yaptıkları son şey bir disply olduğu için her zaman çalışır. orijinal dönüş değerini ve görüntüledikten sonra döndürürler.Bu nedenle, bunu sadece bir gözlemciye gösterirler, ancak komut dosyasının geri kalanı için "gizlerler", bu önemli komutun geri dönüp dönmediğini görmek için "$?" 0 ya da başka bir şey ...)
Olivier Dulac

1
Ayrıca aşağıdaki tüm çözümler bu işlevselliği kolayca uygulayabilir. Örneğin, Kusalananda şöyle olur:EXIT_CODE=$(tellexit command)
jesse_b

Yanıtlar:


4

Şimdiye kadar yaptığım testte bu işe yaradı:

command && echo "$?" || echo "$?"

Sadece başarılı olursa veya başarısız olursa çıkış kodunun yankılanmasını söyler.

Sato'nun aşağıda belirttiği gibi, bu aslında aynıdır:

command; echo "$?"

Ve / veya komutunu değerli kılabilecek bir şey şudur:

command && echo "Success! Exit Code: $?" || echo "Failure! Exit Code: $?"

Komut dosyanızın Olivier'in endişesi gibi çıkış koduna göre hareket etmesi gerekiyorsa bu bir sorun değildir. Senaryonuz şöyle görünebilir:

command
case "$?" in; 
    0) echo "Command exited with: 0"
       <command if good>
       ;;
    1) echo "Command exited with: 1"
        <command if bad>
        ;;
    255) echo "Command exited with: 255"  # for ssh maybe?
         <command if 255>
         ;;
    *) echo "Command exited with: >2"
        <command for other exit code>
        ;;
esac

13
Err, bu sadece bundan daha iyi nasıl command; echo $??
Satō Katsura

4
Sanırım öyle değil. command; echo $?çok daha iyi bir cevap.
jesse_b

uhhh bu en iyi seçenek gibi görünüyor, bu yüzden cevap olarak seçtim, kimse katılmıyorum, lmk
Alexander Mills

@AlexanderMills Sorunuza en uygun cevabın sadece siz olduğunu biliyorsunuz :-)
Kusalananda

1
Bunu beğenmedim: Bundan sonra çıkış kodu değiştirir command ; echo $?çünkü echo $?, bu nedenle ondan sonra Doları yeni bir değer her zaman başarılı ve? Orijinal dönüş kodunun daha sonra yararlı olması durumunda, orijinal dönüş kodunu görüntüledikten sonra bile korumanın bir yolu vardır (Örneğin: bir komut dosyasında, nasıl devam edileceğine karar vermeden önce dönüş kodunu kontrol etmek önemlidir). Birkaç çözümden biri için cevabımı görün (buradaki cevapların çoğu aynı şekilde değiştirilebilir)
Olivier Dulac

11

cmd && echo "$?"sadece sıfır basması gerektiği için işe yaramaz ( echoyalnızca önceki komutun başarılı bir şekilde tamamlanmasıyla çalışır).

İşte size kısa bir kabuk işlevi:

tellexit () {
    "$@"

    local err="$?"
    printf 'exit code\t%d\n' "$err" >/dev/tty
    return "$err"
}

Bu, verilen komutun çıkış kodunu timekomutun yaptığı gibi yazdırır .

$ tellexit echo "hello world"
hello world
exit code       0

$ tellexit false
exit code       1

Yönlendirerek printfiçin /dev/ttyişlevinde, hala kullanabilir tellexitstandart çıkış veya hata akışlarında önemsiz almadan yönlendirmeler ile:

$ tellexit bash -c 'echo hello; echo world >&2' >out 2>err
exit code       0
$ cat out
hello
$ cat err
world

Çıkış kodunu bir değişkene kaydederek arayana geri döndürebiliriz:

$ tellexit false || echo 'failed'
exit code       1
failed

Aynı işlevin daha ince bir sürümü de, çıkış kodu 128'den büyükse komutu öldüren sinyali yazdırır (yani bir sinyal nedeniyle sonlandırılır):

tellexit () {
    "$@"

    local err="$?"

    if [ "$err" -gt 128 ]; then
        printf 'exit code\t%d (%s)\n' "$err" "$(kill -l "$err")" >/dev/tty
    else
        printf 'exit code\t%d\n' "$err" >/dev/tty
    fi

    return "$err"
}

Test yapmak:

$ tellexit sh -c 'kill $$'
exit code       143 (TERM)

$ tellexit sh -c 'kill -9 $$'
Killed
exit code       137 (KILL)

( localŞey ash/ pdksh/ bash/ gerektirir zshveya typesetbirkaç merminin de anladığı şekilde değiştirebilirsiniz.)


havalı, tellexit'i nasıl kullanırsınız, eylemde gösterin pls
Alexander Mills

1
@AlexanderMills Güncellemeye bakın.
Kusalananda

2
Orijinal dönüş değerini korumalı ve sonunda iade etmelidir.
Olivier Dulac

@OlivierDulac Gerçekten iyi bir gözlem! Değiştireceğim.
Kusalananda

7

Bir kabuk sarmalayıcı işlevini kullanın. Muhtemelen farklı bir isimle.

$ exito() { "$@"; echo $?; }
$ exito true
0
$ exito false
1
$ exito echo "test test"      
test test
0
$ 

(Bu elbette standart çıktıyı ttybozar , bu yüzden ya @Kusalananda tarafından gösterildiği gibi kullanın veya etkileşimli bağlamların dışında kullanmayın.)

Kaydedilemez bir bölgeye yönelen bazı mermiler, sadece sonuncuyu değil, bir boru hattındaki tüm komutların durumu hakkında rapor verebilir, örneğin, tüm bir boru hattından arıza bildirilmesini istiyorsanız: ZSH'de:

% TRAPZERR() { print >/dev/tty $pipestatus }
% perl -e 'exit 42' | perl -e 'exit 99'
42 99
% false | perl -e 'exit 42' | perl -e 'exit 99'
1 42 99
% perl -e 'exit 42' | perl -e 'exit 99' | true
% 

TRAPZERR aksi takdirde hata olmazsa ateşlenmez ("hiçbir haber iyi haber değildir" prensibi).


1
Orijinal dönüş değerini korumalı ve sonunda iade etmelidir. (Printf, echo) görüntülenmesi basit bir şeydir ('-' vb. İle başlamaz) her zaman çalışır ve bundan sonra "$?" artık ekran 0 "0" değerine sahip
Olivier Dulac

7

GNU timebunun için bir seçeneğe sahiptir:

time -f %x sleep 1
0

Bir sinyal 2 tarafından öldürülmedikçe çıkış kodu 1'den geçer :

$ /usr/bin/time -f %x sleep 1; echo $?
0
0

$ /usr/bin/time -f %x sleep 2x; echo $?
sleep: invalid time interval ‘2x’
Try 'sleep --help' for more information.
1
1

$ /usr/bin/time -f %x sleep 60s; echo $? # Press ^C before a minute elapses
0
2

Sinyal öldürme durumunu bilmek / işlemek istiyorsanız -v, stderr'ı dize için geçirin ve grep Command terminated by signal.


1 Olivier Dulac'a çıkış kodunun geçtiği için teşekkür ederiz.
2 Ayrıca, Stéphane Chazelas öldürme sinyali çıkış kodunu geçtiği için teşekkür ederiz geçmez.


1
İnterresting. Sadece GNU ama interresting, çünkü kodun geri kalanı için orijinal dönüş kodunu (muhtemelen) takip edecek (diğer cevapların yaptığı gibi "0" ile değiştirmez)
Olivier Dulac

2
0Komut öldürülürse geri döner .
Stéphane Chazelas

2
@bishop, bu durumlarda 0'ın idealden daha az olduğunu kabul ediyorum. Ancak, bir komut bir sinyal tarafından öldürüldüğünde neyin rapor edileceğine dair genel bir anlaşma olmadığını unutmayın. Dönen 128 + sinyal sayısı birkaç mermi tarafından kullanılır. Ayrıca benzer şeyleri görmek 256+signumveya 384+signumhatta signum/256ya signum/256+0.5bir çekirdek oluşturulmuştur if (aslında tarafından döndürülen durum waitpid()256 bölü). Bazıları metinsel bir sunum ( sigintveya gibi sigquit+core) verebilirdi . Yine de muhtemelen gnu.coreutils.bugs haber grubunda tartışmaya değer.
Stéphane Chazelas

3
(aslında timebir parçası değildir , kendi hata posta listesiyle kendi başınacoreutils bir pakettir (bug-time@gnu.org))
Stéphane Chazelas

1
@bishop, system()Brian Kernighan ( kin awk) ya da FreeBSD'nin nawkSolaris tarafından sürdürülen gibi geleneksel garipler awk. awk 'BEGIN{print system("kill -s ABRT $$")}'çıkışları 0.523438çekirdek döküm boyutu sınırlı değilken. Davranışı gawkile davranışı değişen, son değişmiş --traditionalya da --posix(aynı zamanda dönüş değeri bakınız close(cmd)daha fazla varyasyon)
Stéphane Chazelas

2

Diğer tüm cevapları sevmiyorum (zeki olmaları için çok hoşuma gitmesine rağmen): çıkış kodunu görüntülerler, ancak aynı zamanda BT DEĞİŞTİRİRLER. (görüntülenen kısım doğrudur, bundan sonra dönüş kodu 0'dır)

İşte değiştirilmiş bir sürüm:

do_and_tell () {
   "$@"
   returncode="$?"
   printf "Execution of : \n%s\n yelded a return code of: \n%s\n" "$*" "$returncode"
   return $returncode  # the interresting addition... keeps the commands return value.
}

## usage:

prompt$ do_and_tell true
Execution of : 
true
 yelded a return code of: 
0

prompt$ echo $?
0

prompt$ do_and_tell false
Execution of : 
false
 yelded a return code of: 
1

prompt$ echo $?
1

aslında @bishop cevabı bu değeri koruyan ancak GNU'nun timeher zaman mevcut olmayan versiyonuna dayanan tek cevaptır .
Olivier Dulac

2

Biraz daha sağlam olmak için, çıkış durumunu ayrı bir FD'ye gönderin, böylece stdout / stderr'den bağımsız olarak işlenebilir:

exit_status() {
    "$@"
    rv=$?
    echo >&3 "$rv"
    return "$rv"
}

# exit status and stdout to stdout:
> exit_status echo "hello" 3>&1
hello
0

# exit_status to stdout, stdout to /dev/null
> exit_status echo "hello" 3>&1 1>/dev/null
0
> exit_status ehco "hello" 3>&1 1>/dev/null
ehco: command not found
127

# exit_status to stdout, stdout and stderr to /dev/null
> exit_status ehco "hello" 3>&1 &>/dev/null
127

FD3 ile bir şeyler yapmanız gerektiğini unutmayın, ya da söyleyecektir Bad file descriptor.

Bu, diğer programın birden fazla FD üzerinde dinlemesini sağlayarak, bu çıkışları başka bir programın girişlerine sağlayacak şekilde yapılandırılabilir; bunu bir çeşit 90'ların Kibana'sı olarak kullanabilirsiniz :)


Orijinal dönüş değerini korumalı ve sonunda iade etmelidir. (Printf, echo) görüntülenmesi basit bir şeydir ('-' vb. İle başlamaz) her zaman çalışır ve bundan sonra "$?" artık ekran 0 "0" değerine sahip
Olivier Dulac

1

Diğer tüm (çok ilginç) cevaplar hitap ederken tam OP pratikte sorulan soru, işler genellikle daha basittir. Çıkış durumunu bir değişkene (komutun hemen ardından) kaydeder ve istediğiniz şekilde raporlar veya kaydedersiniz. / Dev / stderr dosyasına yazdırın veya bir günlük dosyasına metin mesajı olarak yazın / ekleyin. Ayrıca, sonraki kodda karar verme / akış kontrolünde kullanım için de korunmuştur.

Bir işlevdeyse:

function some-function () {
    local rc ## to avoid side effects
    ...
    some-command ## run any command
    rc=$?  ## save the return status in a variable
    echo "some-command returned $rc" ## optionally tell the user about it
    ...
    return $rc  ## at the end, if appropriate
}

Doğrudan bir komut dosyasındaysa:

some-command ## run any command
rc=$?  ## save the return status in a variable
echo "some-command returned $rc" ## optionally tell the user about it
...
exit $rc    ## at the end to tell any calling script about it, if appropriate

(Ördek ve örtme çünkü bu kesin soruya cevap vermiyor .)

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.