Apa artinya `{{(keluar 1); keluar 1; }; } `berarti?

28

Saya mengutip potongan kode selanjutnya dari yang config.statusdihasilkan oleh configure.

if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi

Dalam cuplikan kode, apa fungsinya { (exit 1); exit 1; };? Apa tujuan dari hanya melakukan exitdalam subkulit?

MS.Kim
sumber

Jawaban:

33

Eksekusi (exit 1);adalah cara paling sederhana untuk memicu ERRjebakan. Ini juga akan memicu keluar segera jika set -esedang berlaku. (Memicu kondisi kesalahan memerlukan perintah untuk gagal; exitdengan nilai kegagalan dalam subkulit menyebabkan subkulit gagal.)

exit 1; tidak akan melakukan hal-hal itu.

Jadi {(exit 1); exit 1;}dapat digunakan untuk pertama-tama menghasilkan ERRjebakan, yang mungkin melakukan sesuatu yang berguna untuk tujuan debugging, dan kemudian mengakhiri skrip dengan indikasi kesalahan.

Tapi bukan itu yang terjadi dalam autoconffile. autoconfskrip mengandalkan EXITjebakan untuk membersihkan file sementara yang dibuat selama proses. Kebanyakan shell, termasuk bashakan mengatur status dari nilai yang disediakan dalam exitperintah sebelum memanggil EXITjebakan. Itu dapat memungkinkan EXITperangkap untuk mendeteksi apakah itu dipanggil dari kesalahan atau dari penghentian normal, dan itu juga memungkinkan untuk memastikan bahwa status keluar diatur dengan benar di akhir operasi perangkap.

Namun, tampaknya beberapa cangkang tidak bekerja sama. Berikut ini kutipan dari autoconfmanual :

Beberapa skrip shell, seperti yang dihasilkan oleh autoconf, menggunakan perangkap untuk membersihkan sebelum keluar. Jika perintah shell terakhir keluar dengan status bukan nol, jebakan juga keluar dengan status bukan nol sehingga penyerang dapat mengetahui bahwa terjadi kesalahan.

Sayangnya, dalam beberapa shell, seperti Solaris /bin/sh, trap keluar mengabaikan argumen perintah keluar. Dalam shell ini, jebakan tidak dapat menentukan apakah itu dipanggil dengan keluar biasa atau dengan keluar 1. Alih-alih memanggil keluar secara langsung, gunakan AC_MSG_ERRORmakro yang memiliki solusi untuk masalah ini.

Solusi adalah untuk memastikan bahwa $?memiliki status exit sebelum itu exitperintah dijalankan, sehingga pasti akan memiliki nilai bahwa ketika EXITperangkap dijalankan. Dan, memang, itu adalah AC_MSG_ERRORmakro yang menyisipkan kode aneh itu, lengkap dengan kawat gigi redundan.

Rici
sumber
Kenapa tidak dieksekusi falsesaja (exit 1)?
Ruslan
3
@Ruslan: Dua masalah. (1) Paling penting: falsejangan biarkan Anda mengatur kode status dan tidak ada jaminan untuk apa status non-nol itu dikembalikan. (2) falsebiasanya tidak builtin, sehingga membutuhkan proses anak; sebaliknya, sebagian besar cangkang dapat menghindari pemijahan anak untuk ditangani (exit 1).
rici
8

Tidak ada tujuan untuk ini sejauh yang saya lihat, tidak ada yang dapat dicapai secara langsung dengan memulai subkulit dan kemudian segera keluar.

Hal-hal seperti ini kemungkinan besar merupakan efek samping dari pembuatan kode secara otomatis - dalam beberapa kasus mungkin ada perintah lain yang dijalankan dalam subkulit di mana memiliki exit 1akal. Pada akhirnya ada peluang yang baik bahwa kode generasi entah bagaimana disederhanakan dengan membiarkannya memasukkan beberapa pernyataan yang tidak memiliki fungsi dalam beberapa kasus dan menghasilkan 'kode bersih' setiap kali lebih kompleks. Entah itu atau kode yang menghasilkan di atas ditulis dengan buruk :)

Penggunaan liberal {...}adalah contoh lain dari ini, kebanyakan dari mereka berlebihan, tetapi lebih mudah untuk menulis kode yang menyisipkan mereka dalam setiap kasus (mungkin dalam beberapa Anda ingin mengarahkan output / input dari blok) daripada membedakan yang tidak dibutuhkan dan dihilangkan.

Graeme
sumber
Itu memang memiliki tujuan. Lihat jawaban @ rici.
Old Pro
1

(exit 1)adalah cara yang sederhana, mungkin cara paling sederhana untuk mendapatkan kode keluar tertentu (dalam kasus khusus 1 ada cara yang lebih mudah, tentu saja). Tapi itu bukan alasan dalam hal ini karena kode keluar tidak diperiksa.

Tujuan memasukkan exitsubkulit mungkin untuk tidak keluar dari skrip (meskipun menggunakan keluar untuk pembuatan kode keluar tertentu).

Hauke ​​Laging
sumber