2012-01-12 40 views
11

Làm cách nào để lấy mã trả về chính xác từ ứng dụng dòng lệnh unix sau khi tôi đã chuyển nó qua một lệnh khác đã thành công?Đầu ra của lệnh đường ống, nhưng giữ mã lỗi

Cụ thể, đây là tình hình:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} -- when only the tar command fails $?=0 
$ echo $? 
0 

Và, những gì tôi muốn thấy là:

$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file} 
$ echo $? 
1 

Có ai biết làm thế nào để thực hiện điều này?

+0

'$?' Giữ mã lỗi. Bạn có thể lưu nó trong một biến. –

+1

tôi cần lưu mã trả về của lệnh trung gian, không phải lệnh cuối cùng. – SamiBOB

Trả lời

3

Đây là giải pháp chung chỉ sử dụng trình bao POSIX và không có tệp tạm thời:

Bắt đầu từ đường ống: foo | thanh | baz

exec 4>&1 
error_statuses=`((foo || echo "0:$?" >&3) | 
     (bar || echo "1:$?" >&3) | 
     (baz || echo "2:$?" >&3)) 3>&1 >&4` 
exec 4>&- 

$ error_statuses chứa các mã trạng thái của bất kỳ quy trình không thành công, theo thứ tự ngẫu nhiên, cho biết lệnh nào phát ra từng trạng thái.

# if "bar" failed, output its status: 
echo $error_statuses | grep '1:' | cut -d: -f2 

# test if all commands succeeded: 
test -z "$error_statuses" 

# test if the last command succeeded: 
echo $error_statuses | grep '2:' >/dev/null 
4

Nhìn vào $PIPESTATUS là biến mảng giữ trạng thái thoát. Vì vậy, ${PIPESTATUS[0]} giữ trạng thái thoát của lệnh đầu tiên trong đường ống, ${PIPESTATUS[1]} trạng thái thoát của lệnh thứ hai, v.v.

Ví dụ:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} 
$ echo ${PIPESTATUS[0]} 

Để in ra tất cả các trạng thái sử dụng:

$ echo ${PIPESTATUS[@]} 
+1

Thx, nhưng tôi không sử dụng bash với tập lệnh của mình. Tôi làm việc với #!/Bin/sh – SamiBOB

+0

@dogbane, bất kỳ sự khác biệt nào giữa '$ {PIPESTATUS [*]}' và '$ {PIPESTATUS [@]}'? Tôi luôn sử dụng tên cũ ... – fge

+2

Được bỏ qua, $ PIPESTATUS ** KHÔNG tồn tại ** trong POSIX. –

1

Như những người khác đã chỉ ra, một số vỏ hiện đại cung cấp PIPESTATUS để nhận thông tin này. Trong sh cổ điển, điều này hơi khó khăn hơn và bạn cần sử dụng một số năm:

 
#!/bin/sh 

trap 'rm -rf $TMPDIR' 0 
TMPDIR=$(mktemp -d) 
mkfifo ${FIFO=$TMPDIR/fifo} 

cmd1 > $FIFO & 
cmd2 < $FIFO 
wait $! 
echo The return value of cmd1 is $? 

(Vâng, bạn không cần sử dụng FIFO. Bạn có thể có các lệnh sớm trong đường ống phản hồi trạng thái biến và eval trong shell chính, chuyển hướng các bộ mô tả tập tin khắp nơi và uốn cong về phía sau để kiểm tra mọi thứ, nhưng sử dụng một nămo là dễ dàng hơn nhiều.)

+0

Xin chào, tôi đã thử kỹ thuật này nhưng nó không có đường nối để làm việc: Tôi đã thử nghiệm:/usr/bin/tar -cMEvhf - -I/tmp/test.tmp> $ FIFO & gzip -5 -c < $FIFO > /tmp/test.bkz đợi $! echo Giá trị trả về của cmd1 là $? – SamiBOB

+0

Lỗi nào bạn nhận được? –

+0

ngay cả khi cmd1 không thành công, $? = 0 – SamiBOB

Các vấn đề liên quan