Lệnh Unix trả về ngay một mã trả về cụ thể?


28

Có một lệnh Unix tiêu chuẩn thực hiện một cái gì đó tương tự như ví dụ của tôi dưới đây không

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

<cmd here>phải là một cái gì đó có thể được thực thi rẽ nhánh và để lại 56 làm mã thoát khi quá trình thoát. Các nội trang exitreturnshell không phù hợp với những gì tôi đang tìm kiếm vì chúng ảnh hưởng đến chính vỏ gọi bằng cách thoát ra khỏi nó. <some cmd>phải là một cái gì đó mà tôi có thể thực thi trong các bối cảnh không có vỏ - ví dụ, gọi từ một kịch bản Python với subprocess.

Ví dụ: /usr/bin/falseluôn thoát ngay lập tức với mã trả về 1, nhưng tôi muốn kiểm soát chính xác mã trả về đó là gì. Tôi có thể đạt được kết quả tương tự bằng cách viết kịch bản trình bao bọc của riêng tôi

$ 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

nhưng tôi hy vọng sẽ tồn tại một lệnh Unix tiêu chuẩn có thể làm điều này cho tôi.


10
exitlà người duy nhất tôi có thể nghĩ ra, nhưng nó có xu hướng kết thúc vỏ của bạn. bash -c 'exit 56'hoặc bash -c "exit $1"có thể làm việc cho bạn.
Tim Kennedy

12
Thế còn (exit 56)?
cuonglm

6
Điều này thực sự nghe giống như một XYPro Hiệu : mục tiêu cuối cùng của việc này là gì? Tại sao bạn cần một lệnh trả về dưới dạng mã thoát số bạn đưa ra?
Olivier Dulac

1
Chà, bạn có truevà tích falsehợp sẵn nếu bạn cần trả về 0 hoặc 1.
vườn

1
có liên quan: chương trình nhỏ nhất (không di động) để trả về giá trị cố định thời gian biên dịch: muppetlabs.com/~breadbox/software/tiny/teensy.html
Florian Castellane

Câu trả lời:


39
  1. Một returnchức năng dựa trên sẽ hoạt động và tránh sự cần thiết phải mở và đóng một lớp vỏ khác, (theo nhận xét của Tim Kennedy ):

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

    Đầu ra:

    56
  2. sử dụng exittrong một lớp con:

    (exit 56)

    Với các loại vỏ khác ksh93, điều đó hàm ý việc tạo ra một quy trình bổ sung nên kém hiệu quả hơn so với quy trình trên.

  3. bash/ zsh/ ksh93chỉ lừa:

    . <( echo return 56 )

    (điều đó cũng bao hàm một quá trình bổ sung (và IPC với một đường ống)).

  4. zshChức năng lambda:

    (){return 56}

Tư tưởng tốt. Thật không may, câu hỏi ban đầu của tôi không được xác định rõ ràng - cần phải "mở và đóng một vỏ khác" gần như là một yêu cầu của những gì tôi muốn làm. Tôi đã chỉnh sửa câu hỏi của mình để yêu cầu đó <some cmd>là một điều thực thi () - có thể.
Chris

2
@Chris: Đối với bất kỳ lệnh shell nào, bạn có thể làm cho nó thực thi () bằng cách chuyển đổi nó thành/bin/sh -c ...originalcommand...
psmears

3
Tôi hơi thất vọng vì điều đó? = 56 không hoạt động.
Joshua

@Joshua: có lẽ vậy? Nhưng sau đó, sự ảnh hưởng này đã thành công và bạn có $? được đặt thành 0 ...;)
Olivier Dulac

@OlivierDulac: Không. Nó phun ra một lỗi phân tích cú pháp.
Joshua

17

Không có lệnh UNIX tiêu chuẩn cho việc chỉ trả về một giá trị cụ thể. Các ứng dụng GNU Core cung cấp truefalseduy nhất.

Tuy nhiên, bạn có thể dễ dàng thực hiện điều này như ret:

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

Biên dịch:

cc ret.c -o ret

Và chạy:

./ret 56 ; echo $?

Bản in:

56

Nếu bạn cần điều này để hoạt động ở mọi nơi (nơi có sẵn bash) mà không cần cài đặt bất kỳ công cụ bổ sung nào, có lẽ bạn cần phải sử dụng lệnh sau như @TimKennedy đã đề xuất trong các nhận xét:

bash -c 'exit 56'

Lưu ý rằng phạm vi giá trị trả về hợp lệ là 0..255 .


1
truefalsecũng có trong Unix (và thậm chí POSIX), không chỉ trong GNU.
Stéphane Chazelas

@ StéphaneChazelas Cảm ơn bạn đã chỉ ra điều đó. Như OP đã đề cập đến bash, bằng cách nào đó tôi đã giả sử GNU - mặc dù bản thân câu hỏi nêu rõ 'Unix'.
tmh

14

Nếu bạn cần trạng thái thoát được thiết lập bởi một lệnh được thực thi. Không có lệnh chuyên dụng cho 1 đó , nhưng bạn có thể sử dụng trình thông dịch của bất kỳ ngôn ngữ nào có khả năng thoát với trạng thái thoát tùy ý. shlà một trong những rõ ràng nhất:

sh -c 'exit 56'

Với hầu hết các shtriển khai, điều đó giới hạn ở các mã thoát 0 đến 255 ( shsẽ chấp nhận các giá trị lớn hơn nhưng có thể cắt bớt nó hoặc thậm chí khiến tín hiệu được gửi đến quá trình thực thi shnhư với ksh93 cho các mã từ 256 đến 320).

Mã thoát có thể là bất kỳ intgiá trị số nguyên ( ) nào nhưng lưu ý rằng bạn cần truy xuất nó bằng waitid()giao diện để giá trị không bị cắt ngắn thành 8 bit (trên Linux, waitid()mặc dù vậy nó vẫn bị cắt cụt ). Do đó, tại sao hiếm khi sử dụng mã thoát trên 255 (sử dụng 0-123 cho hoạt động bình thường).

Cách khác:

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

(những người không cắt ngắn mã thoát thành 8 bit).

Với NetBSD find, bạn có thể làm:

find / -exit 56

1exit là lệnh tiêu chuẩn để làm điều đó nhưng là một hàm dựng sẵn đặc biệt , không có yêu cầu rằng cũng có một lệnh có tên đó trong hệ thống tệp như đối với các tệp dựng sẵn thông thường và hầu hết các hệ thống sẽ không bao gồm một lệnh


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]);
}

Lưu cái này trong một tập tin có tên returncode.cgcc -o returncode returncode.c


Trên một lưu ý liên quan đến bán: 1) áp dụng giấy phép Muff mà không đặt tên cho mình như một người khẳng định có lẽ không phải là một ý tưởng hay và bạn nên làm như vậy , 2) các chương trình nhỏ này quá tầm thường đối với bản quyền của bạn, vì vậy bạn cũng có thể để lại giấy phép.
Hình thoi

2
(1) Tôi không hiểu tại sao bạn sử dụng argv[argc-1]thay vì argv[1]và tại sao bạn không phàn nàn nếu argc>2. (2) Tôi muốn làm argv[1]bài kiểm tra trước khi argv[0]kiểm tra, cho phép người dùng nói true 56hoặc false 56thay vì returncode 56. Bạn không đưa ra một thông điệp nếu argv[0]là một từ và argc>0- điều đó có thể gây nhầm lẫn. (3) Tôi bị ám ảnh bởi sự thân thiện với người dùng, vì vậy tôi sẽ sử dụng strcasecmpthay vì strcmp. (4) Tôi có xu hướng xác nhận các tham số và không sử dụng giá trị trả về của atoimà không xác minh nó. Đối với chương trình 2 like như thế này, tôi đoán nó không thành vấn đề.
G-Man nói 'Phục hồi Monica'

@ G-Man Cả truecũng không falsexử lý bất kỳ tranh cãi trong các hệ thống Linux
ThePiercingPrince

OK, điều đó đúng - họ không xử lý bất kỳ đối số nào, bao gồm argv[0]; các chương trình /bin/true/bin/falselà các tệp thực thi khác nhau, với các mã thoát được mã hóa cứng. Bạn đã viết một chương trình có thể được cài đặt là cả hai truefalse(được liên kết), rất thông minh. Nhưng câu hỏi hỏi làm thế nào để có được trạng thái thoát do người dùng chỉ định. Chương trình của bạn trả lời câu hỏi đó, nhưng chỉ khi nó được cài đặt dưới một tên tệp khác. Miễn là bạn vẫn đang nhìn argv, tôi tin rằng làm theo cách tôi đề xuất sẽ duy trì mức độ thông minh, bằng cách tránh sự cần thiết phải có liên kết thứ ba.
G-Man nói 'Phục hồi Monica'

0

Tôi không chắc chắn chính xác nếu vấn đề duy nhất của bạn với exitlệnh là nó đã thoát ra khỏi trình bao hiện tại, nhưng nếu vậy, một lớp con có thể hoạt động.

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

Tôi đã thử nghiệm điều này trên Cygwin Bash ngay bây giờ và nó hoạt động với tôi.

Chỉnh sửa: Xin lỗi tôi đã bỏ lỡ phần chạy nó bên ngoài một bối cảnh shell. Trong trường hợp đó, thsi sẽ không giúp đỡ nếu không gói nó trong một .shtập lệnh và thực thi nó từ môi trường của bạn.


4
$(exit 42)cố gắng thực hiện đầu ra của exit 42một lệnh đơn giản mà không có ý nghĩa gì (nó cũng không hoạt động với yash). (exit 42)(cũng chạy exittrong một lớp con, nhưng chỉ để lại đầu ra của nó) sẽ có ý nghĩa hơn và sẽ dễ mang theo hơn (ngay cả với vỏ csh hoặc vỏ Bourne).
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.