Ambil kode keluar dari perintah keluar

10

Saya memilikinya di skrip bash:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

Sepertinya akan keluar tepat setelah perintah keluar, yang masuk akal. Saya bertanya-tanya apakah ada beberapa perintah sederhana yang dapat memberikan kode keluar tanpa keluar segera?

Saya akan menebak:

exec exit 3

namun memberikan pesan kesalahan: exec: exit: not found. Apa yang dapat saya? :)

G-Man Mengatakan 'Reinstate Monica'
sumber
1
Ya exec exit 3bukan bueno, saya dapatkan"exec: exit: not found"
7
Saya tidak mengerti pertanyaannya. Mengapa tidak mengatur exit_code=3dan menghilangkan exit 3garis sama sekali?
wjandrea
@wjandrea lebih merupakan pertanyaan konseptual daripada praktis
2
Itu masih tidak masuk akal bagi saya. Mengapa ada kode keluar jika Anda tidak benar-benar keluar?
Barmar
1
@Barmar setiap proses memiliki kode keluar. Sebagian besar orang yang mencoba menjawab pertanyaan menafsirkan pertanyaan dengan maksud "apa yang bisa saya ganti dengan 'exit 3' dengan dalam skrip sehingga ia menetapkan $?variabel tetapi tidak keluar dari skrip ini "?
icarus

Jawaban:

32

Jika Anda memiliki skrip yang menjalankan beberapa program dan melihat status keluar program (dengan  $?), dan Anda ingin menguji skrip itu dengan melakukan sesuatu yang menyebabkan $?disetel ke nilai yang diketahui (misalnya,  3), lakukan saja

(exit 3)

Tanda kurung membuat sub-shell. Kemudian exitperintah menyebabkan sub-shell untuk keluar dengan status keluar yang ditentukan.

G-Man Mengatakan 'Reinstate Monica'
sumber
Selain itu, untuk keperluan debugging, pengaturan exit_code="3"pengujian akan
sesederhana mungkin
1
Ya, wjandrea menunjukkan itu kemarin.
G-Man Mengatakan 'Reinstate Monica'
12

exitadalah bash built-in, jadi Anda tidak bisa execmelakukannya. Manual per bash :

Status keluar Bash adalah status keluar dari perintah terakhir yang dijalankan dalam skrip. Jika tidak ada perintah yang dijalankan, status keluar adalah 0.

Menyatukan semua ini, saya katakan satu-satunya pilihan Anda adalah menyimpan status keluar yang Anda inginkan dalam sebuah variabel dan kemudian exit $MY_EXIT_STATUSjika perlu.

solarshado
sumber
hmmm apa pendapatmu tentang ide G-man?
2
Mungkin saya salah mengerti apa yang ingin Anda capai. Jika Anda hanya mencoba mengatur $?(walaupun saya tidak begitu yakin mengapa Anda mau), itu sepertinya jawaban yang solid. Jika Anda hanya ingin mengaturnya ke beberapa nilai yang gagal, falseadalah pilihan lain.
solarshado
10

Anda dapat menulis fungsi yang mengembalikan status yang diberikan sebagai argumen, atau 255jika tidak ada yang diberikan. (Saya menyebutnya retsebagai "mengembalikan" nilainya.)

ret() { return "${1:-255}"; }

dan gunakan retdi tempat panggilan Anda ke exit. Ini menghindari ketidakefisienan membuat sub-shell dalam jawaban yang saat ini diterima.

Beberapa pengukuran.

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

pada komputer saya membutuhkan sekitar 3,5 detik.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

pada komputer saya membutuhkan waktu sekitar 0,051 detik, 70 kali lebih cepat. Menempatkan penanganan standar masih menyisakan 60 kali lebih cepat. Jelas loop memiliki beberapa overhead. Jika saya mengubah tubuh loop menjadi hanya :atau truekemudian waktunya dibagi dua menjadi 0,025, loop yang benar-benar kosong adalah sintaks yang tidak valid. Menambahkan ;:ke loop menunjukkan bahwa perintah minimal ini memakan waktu 0,007 detik, sehingga overhead loop adalah sekitar 0,018. Mengurangi overhead ini dari dua tes menunjukkan bahwa retsolusinya lebih dari 100 kali lebih cepat.

Jelas ini adalah pengukuran sintetis, tetapi banyak hal bertambah. Jika Anda membuat semuanya 100 kali lebih lambat dari yang seharusnya, maka Anda akan mendapatkan sistem yang lambat. 0,0

icarus
sumber
2
@ iBug Ruang tambahan tidak diperlukan.
icarus
Poin bagus tentang inefisiensi pembuatan sub-shell. Saya telah membaca bahwa beberapa shell mungkin cukup pintar untuk mengoptimalkan garpu dalam kasus-kasus seperti ini, tetapi bash itu bukan salah satunya.
G-Man Mengatakan 'Reinstate Monica'
3

Tentang exec exit 3... itu akan mencoba menjalankan perintah eksternal yang disebut exit, tetapi tidak ada, sehingga Anda mendapatkan kesalahan. Itu harus berupa perintah eksternal alih-alih yang ada di dalam shell, karena exec menggantikan shell sepenuhnya. Yang juga berarti bahwa bahkan jika Anda memiliki perintah eksternal yang dipanggil exit, exec exit 3tidak akan kembali untuk melanjutkan skrip shell Anda, karena shell tidak akan ada lagi .

ilkkachu
sumber
1
Saya kira Anda bisa melakukannya exec bash -c "exit 3", tetapi saat ini saya tidak dapat memikirkan alasan untuk melakukan itu sebagai lawan dari adil exit 3.
David Z
1
@ DavidZ, dalam hal apa pun, exec'ing atau just exit' ing akan menghentikan skrip, yang sepertinya bukan pertanyaan yang diinginkan.
ilkkachu
3

Anda dapat melakukan ini dengan Awk:

awk 'BEGIN{exit 9}'

Atau Sed:

sed Q9 /proc/stat
Steven Penny
sumber
... atau dengan cangkang:sh -c 'exit 9'
ilkkachu
1
@ilkkachu jika Anda akan melakukan itu Anda mungkin juga melakukan (exit 9)jawaban yang diterima
Steven Penny