Perintah Unix yang segera mengembalikan kode pengembalian tertentu?


28

Apakah ada perintah Unix standar yang melakukan sesuatu yang mirip dengan contoh saya di bawah ini

$ <cmd here> 56
$ echo Return code was $?
Return code was 56
$

<cmd here>harus menjadi sesuatu yang bisa di-fork dan meninggalkan 56 sebagai kode keluar saat proses keluar. The exitdan returnshell builtin tidak cocok untuk apa yang saya cari karena mereka mempengaruhi shell memohon sendiri dengan keluar dari itu. <some cmd>harus menjadi sesuatu yang dapat saya jalankan dalam konteks non-shell - misalnya, meminta dari skrip Python dengan subprocess.

Misalnya, /usr/bin/falseselalu keluar segera dengan kode kembali 1, tetapi saya ingin mengontrol apa itu kode kembali. Saya dapat mencapai hasil yang sama dengan menulis skrip pembungkus saya sendiri

$ cat my-wrapper-script.sh # i.e., <some cmd> = ./my-wrapper-script.sh
#!/usr/bin/bash
exit $1
$ ./my-wrapper-script.sh 56
$ echo $?
56

tapi saya berharap kebetulan ada perintah Unix standar yang dapat melakukan ini untuk saya.


10
exitadalah satu-satunya yang bisa saya pikirkan, tetapi cenderung mengakhiri cangkang Anda. bash -c 'exit 56'atau bash -c "exit $1"mungkin bekerja untuk Anda.
Tim Kennedy

12
Bagaimana dengan (exit 56)?
cuonglm

6
Ini benar-benar terdengar seperti XYProblem : apa tujuan akhir ini? Mengapa Anda memerlukan perintah yang mengembalikan kode keluar nomor yang Anda berikan?
Olivier Dulac

1
Nah, Anda memiliki truedan false
bawaan

1
related: (non portable) program terkecil untuk mengembalikan nilai tetap waktu kompilasi: muppetlabs.com/~breadbox/software/tiny/teensy.html
Florian Castellane

Jawaban:


39
  1. Sebuah returnfungsi berbasis akan bekerja, dan menghindari kebutuhan untuk membuka dan menutup shell lain, (sesuai Tim Kennedy komentar 's ):

    freturn() { return "$1" ; } 
    freturn 56 ; echo $?

    Keluaran:

    56
  2. gunakan exitdalam subkulit:

    (exit 56)

    Dengan cangkang selain ksh93, itu menyiratkan forking proses tambahan sehingga kurang efisien daripada yang di atas.

  3. bash/ zsh/ ksh93hanya trik:

    . <( echo return 56 )

    (Itu juga menyiratkan proses ekstra (dan IPC dengan pipa)).

  4. zshFungsi lambda:

    (){return 56}

Pikiran bagus. Sayangnya, pertanyaan awal saya tidak didefinisikan dengan cukup baik - perlu "membuka dan menutup shell lain" hampir merupakan persyaratan dari apa yang ingin saya lakukan. Saya mengedit pertanyaan saya untuk meminta yang <some cmd>merupakan hal yang dapat dieksekusi ().
Chris

2
@ Chris: Untuk setiap perintah shell Anda dapat membuatnya mengeksekusi () dapat dengan mengubahnya ke/bin/sh -c ...originalcommand...
psmears

3
Saya agak kecewa itu? = 56 tidak bekerja.
Joshua

@ Yosua: mungkin ya? tetapi kemudian pengaruh ini berhasil, dan Anda memiliki $? set ke 0 ...;)
Olivier Dulac

@OlivierDulac: Tidak. Itu memuntahkan kesalahan parse.
Yosua

17

Tidak ada perintah UNIX standar untuk hanya mengembalikan nilai tertentu. Utilitas Inti GNU hanya menyediakan truedan false.

Namun, Anda dapat dengan mudah menerapkan ini sendiri sebagai ret:

#include <stdlib.h>
int main(int argc, char *argv[]) {
  return argc > 1 ? atoi(argv[1]) : 0;
}

Menyusun:

cc ret.c -o ret

Dan lari:

./ret 56 ; echo $?

Cetakan:

56

Jika Anda membutuhkan ini untuk bekerja di mana-mana (di mana bash tersedia, yaitu) tanpa menginstal alat tambahan, Anda mungkin perlu menggunakan perintah berikut seperti yang disarankan @TimKennedy dalam komentar:

bash -c 'exit 56'

Perhatikan bahwa rentang nilai pengembalian yang valid adalah 0..255 inklusif .


1
truedan falseberada di Unix (dan bahkan POSIX) juga, tidak hanya di GNU.
Stéphane Chazelas

@ StéphaneChazelas Terima kasih telah menunjukkannya. Seperti yang disebutkan OP tentang bash, saya entah bagaimana menganggap GNU - meskipun pertanyaannya sendiri menyatakan 'Unix'.
tmh

14

Jika Anda perlu status keluar diatur oleh perintah yang dijalankan. Tidak ada perintah khusus untuk 1 itu , tetapi Anda dapat menggunakan penerjemah bahasa apa pun yang memiliki kemampuan untuk keluar dengan status keluar sewenang-wenang. shadalah yang paling jelas:

sh -c 'exit 56'

Dengan sebagian besar shimplementasi, itu terbatas untuk keluar dari kode 0 hingga 255 ( shakan menerima nilai yang lebih besar tetapi dapat memotongnya atau bahkan menyebabkan sinyal dikirim ke proses yang dijalankan shseperti dengan ksh93 untuk kode 257 hingga 320).

Kode keluar bisa berupa intnilai integer ( ) apa pun, tetapi perhatikan bahwa Anda harus mengambilnya dengan waitid()antarmuka sehingga nilainya tidak terpotong menjadi 8 bit (di Linux, masih terpotong dengan waitid()baik juga). Oleh karena itu mengapa jarang (dan bukan ide yang baik) untuk menggunakan kode keluar di atas 255 (gunakan 0-123 untuk operasi normal).

Kalau tidak:

awk 'BEGIN{exit 56}'
perl -e 'exit 56'
python -c 'exit(56)'
expect -c 'exit 56'

(itu tidak memotong kode keluar menjadi 8 bit).

Dengan NetBSD find, Anda dapat melakukan:

find / -exit 56

1exit adalah perintah standar untuk melakukan itu tetapi menjadi builtin khusus shell , tidak ada persyaratan bahwa ada juga perintah dengan nama itu dalam sistem file seperti untuk built-in biasa, dan kebanyakan sistem tidak akan memasukkan satu


3
/* Public domain, http://creativecommons.org/publicdomain/zero/1.0/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv) {
    if(!strcasecmp(argv[0],"true")) return 0;
    else if (!strcasecmp(argv[0],"false")) return 1;
    else if(argc<2) {fputs("One argument required\n",stderr);return 1;}
    else if(!strcasecmp(argv[argc-1],"true")) return 0;
    else if(!strcasecmp(argv[argc-1],"false")) return 1;
    else return atoi(argv[argc-1]);
}

Simpan ini dalam file bernama returncode.cdangcc -o returncode returncode.c


Pada catatan semi-terkait: 1) menerapkan lisensi CC0 tanpa menyebut diri Anda sebagai affirmer mungkin bukan ide yang baik, dan Anda harus melakukannya seperti ini , 2) program yang kecil ini terlalu sepele untuk hak cipta Anda, sehingga Anda lebih baik tinggalkan lisensi.
Rhymoid

2
(1) Saya tidak mengerti mengapa Anda menggunakan argv[argc-1]bukan argv[1], dan mengapa Anda tidak mengeluh jika argc>2. (2) Saya akan cenderung untuk melakukan argv[1]tes sebelum argv[0]ujian, yang memungkinkan pengguna untuk mengatakan true 56atau false 56bukan returncode 56. Anda tidak memberikan pesan jika argv[0]itu sebuah kata dan argc>0- itu bisa membingungkan. (3) Saya terobsesi dengan user-keramahan, jadi saya akan menggunakan strcasecmpbukan strcmp. (4) Saya cenderung memvalidasi parameter, dan tidak menggunakan nilai balik atoitanpa memverifikasinya. Untuk program 2 ¢ seperti ini, saya kira itu tidak masalah.
G-Man Mengatakan 'Reinstate Monica'

@ G-Man Baik proses truemaupun falseargumen dalam sistem Linux
ThePiercingPrince

OK, itu benar - mereka tidak memproses argumen apa pun, termasuk argv[0]; program /bin/truedan /bin/falsemerupakan executable yang berbeda, dengan kode keluar hard-coded. Anda telah menulis sebuah program yang dapat diinstal sebagai keduanya true dan false(ditautkan), yang cerdik. Tetapi pertanyaannya adalah bagaimana cara mendapatkan status keluar yang ditentukan pengguna. Program Anda menjawab pertanyaan itu, tetapi hanya jika diinstal dengan nama file yang berbeda. Selama Anda argvtetap melihat, saya percaya bahwa melakukannya dengan cara yang saya sarankan akan mempertahankan tingkat kepintaran, dengan menghindari kebutuhan akan tautan ketiga.
G-Man Mengatakan 'Reinstate Monica'

0

Saya tidak yakin apakah satu-satunya masalah Anda dengan exitperintah itu keluar dari shell saat ini, tetapi jika demikian, sebuah subkulit mungkin bekerja.

username@host$ $(exit 42)
username@host$ echo $?
42

Saya menguji ini di Cygwin Bash sekarang dan itu bekerja untuk saya.

Sunting: Maaf saya melewatkan bagian menjalankannya di luar konteks shell. Dalam hal ini, ini tidak akan membantu tanpa membungkusnya dalam .shskrip dan menjalankannya dari lingkungan Anda.


4
$(exit 42)mencoba untuk mengeksekusi output exit 42sebagai perintah sederhana yang tidak masuk akal (itu juga tidak akan bekerja dengan yash). (exit 42)(juga berjalan exitdalam subkulit, tetapi meninggalkan outputnya sendiri) akan lebih masuk akal dan akan lebih portabel (bahkan untuk csh atau shell Bourne).
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.