Cách lưu lỗi tiêu chuẩn trong một biến


182

Hãy nói rằng tôi có một kịch bản như sau:

vô dụng

echo "This Is Error" 1>&2
echo "This Is Output" 

Và tôi có một kịch bản shell khác:

cũng vô dụng.sh

./useless.sh | sed 's/Output/Useless/'

Tôi muốn ghi lại "Đây là Lỗi" hoặc bất kỳ thiết bị lỗi nào khác từ usless.sh, thành một biến. Hãy gọi nó là LRI.

Lưu ý rằng tôi đang sử dụng thiết bị xuất chuẩn cho một cái gì đó. Tôi muốn tiếp tục sử dụng thiết bị xuất chuẩn, vì vậy việc chuyển hướng thiết bị xuất chuẩn thành thiết bị xuất chuẩn là không hữu ích, trong trường hợp này.

Vì vậy, về cơ bản, tôi muốn làm

./useless.sh 2> $ERROR | ...

nhưng điều đó rõ ràng là không hoạt động.

Tôi cũng biết rằng tôi có thể làm

./useless.sh 2> /tmp/Error
ERROR=`cat /tmp/Error`

nhưng đó là xấu xí và không cần thiết.

Thật không may, nếu không có câu trả lời nào xuất hiện ở đây, đó là điều tôi sẽ phải làm.

Tôi hy vọng có một cách khác.

Bất cứ ai có ý tưởng tốt hơn?


4
Chính xác những gì muốn sử dụng thiết bị xuất chuẩn? Bạn chỉ đơn giản muốn xem nó trên bàn điều khiển? Hoặc bạn đang chụp / chuyển hướng đầu ra của nó? Nếu chỉ vào bảng điều khiển, bạn chuyển hướng thiết bị xuất chuẩn sang bảng điều khiển và thiết bị xuất chuẩn để xuất hiện để nắm bắt nó:ERROR=$(./useless.sh | sed 's/Output/Useless/' 2>&1 1>/dev/ttyX)
Tim Kersten

Câu trả lời:


91

Do đó, sẽ gọn gàng hơn để chụp tệp lỗi:

ERROR=$(</tmp/Error)

Shell nhận ra điều này và không phải chạy ' cat' để lấy dữ liệu.

Câu hỏi lớn hơn là khó. Tôi không nghĩ có một cách dễ dàng để làm điều đó. Bạn sẽ phải xây dựng toàn bộ đường ống vào lớp vỏ phụ, cuối cùng gửi đầu ra tiêu chuẩn cuối cùng của nó tới một tệp để bạn có thể chuyển hướng các lỗi sang đầu ra tiêu chuẩn.

ERROR=$( { ./useless.sh | sed s/Output/Useless/ > outfile; } 2>&1 )

Lưu ý rằng dấu chấm phẩy là cần thiết (trong vỏ cổ điển - Bourne, Korn - chắc chắn; có lẽ trong Bash cũng vậy). ' {}' Không chuyển hướng I / O qua các lệnh kèm theo. Như đã viết, nó sẽ nắm bắt lỗi từ sedquá.

CẢNH BÁO: Mã chính thức chưa được kiểm tra - sử dụng có nguy cơ.


1
Tôi đã hy vọng rằng có một số mẹo thực sự điên rồ mà tôi không biết, nhưng có vẻ như đây là nó. Cảm ơn.
psycotica0

9
Nếu bạn không cần đầu ra tiêu chuẩn, bạn có thể chuyển hướng nó đến /dev/nullthay vì outfile(Nếu bạn giống tôi, bạn đã tìm thấy câu hỏi này qua Google và không có các yêu cầu tương tự như OP)
Mark Eirich

2
Đối với một câu trả lời mà không có tập tin tạm thời, xem ở đây .
Tom Hale

1
Đây là một cách để làm điều đó mà không chuyển hướng nó đến các tập tin; Nó chơi với trao đổi stdoutstderrqua lại. Nhưng hãy cẩn thận , như ở đây đã nói: Trong bash, tốt hơn là không cho rằng mô tả tệp 3 không được sử dụng " .
Golar Ramblar

69

cũng vô dụng.sh

Điều này sẽ cho phép bạn dẫn đầu ra của useless.shtập lệnh thông qua một lệnh như sedvà lưu stderrvào một biến có tên error. Kết quả của đường ống được gửi đến stdoutđể hiển thị hoặc được dẫn vào một lệnh khác.

Nó thiết lập một vài mô tả tập tin bổ sung để quản lý các chuyển hướng cần thiết để thực hiện việc này.

#!/bin/bash

exec 3>&1 4>&2 #set up extra file descriptors

error=$( { ./useless.sh | sed 's/Output/Useless/' 2>&4 1>&3; } 2>&1 )

echo "The message is \"${error}.\""

exec 3>&- 4>&- # release the extra file descriptors

4
Đó là kỹ thuật tốt để sử dụng 'exec' để thiết lập và đóng mô tả tập tin. Đóng không thực sự cần thiết nếu tập lệnh thoát ngay sau đó.
Jonathan Leffler

3
Làm thế nào tôi có thể nắm bắt cả hai stderrstdouttrong các biến?
Gingi

Thông minh. Điều này giúp tôi thực hiện một dry_runchức năng có thể lựa chọn một cách đáng tin cậy giữa việc lặp lại các đối số của nó và chạy chúng, bất kể lệnh đang chạy khô có được chuyển sang một số tệp khác hay không.
Mihai Danila

1
@ t00bs: readkhông chấp nhận đầu vào từ một đường ống. Bạn có thể sử dụng các kỹ thuật khác để đạt được những gì bạn đang cố gắng thể hiện.
Tạm dừng cho đến khi có thông báo mới.

2
Có thể đơn giản hơn, với: error = $ (./usless.sh | sed 's / Output / Usless /' 2> & 1 1> & 3)
Jocelyn

64

Chuyển hướng stderr thành stdout, stdout thành / dev / null, sau đó sử dụng backticks hoặc $()để bắt stderr chuyển hướng:

ERROR=$(./useless.sh 2>&1 >/dev/null)

8
Đây là lý do tôi bao gồm các đường ống trong ví dụ của tôi. Tôi vẫn muốn đầu ra tiêu chuẩn, và tôi muốn nó làm những việc khác, đi những nơi khác.
psycotica0

Ví dụ, đối với các lệnh chỉ gửi đầu ra đến stderr, cách đơn giản để nắm bắt nó làPY_VERSION="$(python --version 2>&1)"
John Mark

9

Có rất nhiều bản sao cho câu hỏi này, nhiều trong số đó có kịch bản sử dụng đơn giản hơn một chút trong đó bạn không muốn chụp stderr stdout mã thoát cùng một lúc.

if result=$(useless.sh 2>&1); then
    stdout=$result
else
    rc=$?
    stderr=$result
fi

hoạt động cho kịch bản chung nơi bạn mong đợi đầu ra thích hợp trong trường hợp thành công hoặc thông báo chẩn đoán trên thiết bị lỗi chuẩn trong trường hợp thất bại.

Lưu ý rằng các báo cáo kiểm soát của shell đã kiểm tra $?dưới mui xe; vì vậy bất cứ điều gì trông giống như

cmd
if [ $? -eq 0 ], then ...

chỉ là một cách nói vụng về, không thông thường

if cmd; then ...

Điều này làm việc cho tôi: my_service_status = $ (dịch vụ my_service status 2> & 1) Cảm ơn !!
JRichardsz

6
# command receives its input from stdin.
# command sends its output to stdout.
exec 3>&1
stderr="$(command </dev/stdin 2>&1 1>&3)"
exitcode="${?}"
echo "STDERR: $stderr"
exit ${exitcode}

1
commandlà một lựa chọn tồi ở đây, vì thực sự có một tên được xây dựng theo tên đó. Có thể làm cho nó yourCommandhoặc như vậy, để rõ ràng hơn.
Charles Duffy

4

Vì lợi ích của người đọc, công thức này ở đây

  • có thể được sử dụng lại như oneliner để bắt stderr vào một biến
  • vẫn cấp quyền truy cập vào mã trả về của lệnh
  • Hy sinh một mô tả tập tin tạm thời 3 (tất nhiên bạn có thể thay đổi)
  • Và không để bộ mô tả tập tin tạm thời này cho lệnh bên trong

Nếu bạn muốn bắt stderrmột số commandvào varbạn có thể làm

{ var="$( { command; } 2>&1 1>&3 3>&- )"; } 3>&1;

Sau đó, bạn có tất cả:

echo "command gives $? and stderr '$var'";

Nếu commandđơn giản (không phải như thế a | b), bạn có thể bỏ nội tâm {}:

{ var="$(command 2>&1 1>&3 3>&-)"; } 3>&1;

Được gói gọn trong một bashchức năng dễ sử dụng lại (có thể cần phiên bản 3 trở lên local -n):

: catch-stderr var cmd [args..]
catch-stderr() { local -n v="$1"; shift && { v="$("$@" 2>&1 1>&3 3>&-)"; } 3>&1; }

Giải thích:

  • local -nbí danh "$ 1" (là biến cho catch-stderr)
  • 3>&1 sử dụng mô tả tập tin 3 để lưu các điểm xuất sắc
  • { command; } (hoặc "$ @") sau đó thực thi lệnh trong quá trình bắt đầu ra $(..)
  • Xin lưu ý rằng thứ tự chính xác rất quan trọng ở đây (thực hiện sai cách xáo trộn các mô tả tệp sai):
    • 2>&1chuyển hướng stderrđến việc bắt đầu ra$(..)
    • 1>&3chuyển hướng stdouttừ đầu ra bắt $(..)trở lại "bên ngoài" stdoutđã được lưu trong bộ mô tả tệp 3. Lưu ý rằng stderrvẫn đề cập đến nơi FD 1 đã chỉ trước: Để bắt đầu ra$(..)
    • 3>&-sau đó đóng bộ mô tả tệp 3 vì nó không còn cần thiết nữa, như vậy commandkhông đột nhiên có một số mô tả tệp mở không xác định hiển thị. Lưu ý rằng lớp vỏ bên ngoài vẫn có FD 3 mở, nhưng commandsẽ không nhìn thấy nó.
    • Điều thứ hai là quan trọng, bởi vì một số chương trình như lvmphàn nàn về mô tả tập tin bất ngờ. Và lvmphàn nàn với stderr- chỉ những gì chúng ta sẽ nắm bắt!

Bạn có thể bắt bất kỳ mô tả tập tin nào khác với công thức này, nếu bạn thích ứng. Tất nhiên ngoại trừ mô tả tệp 1 (ở đây logic chuyển hướng sẽ sai, nhưng đối với mô tả tệp 1, bạn chỉ có thể sử dụng var=$(command)như bình thường).

Lưu ý rằng điều này hy sinh bộ mô tả tệp 3. Nếu bạn tình cờ cần bộ mô tả tệp đó, vui lòng thay đổi số. Nhưng hãy lưu ý rằng một số shell (từ những năm 1980) có thể hiểu 99>&1là đối số 9theo sau 9>&1(điều này không có vấn đề gì bash).

Cũng lưu ý rằng không dễ để tạo cấu hình FD 3 này thông qua một biến. Điều này làm cho mọi thứ rất khó đọc:

: catch-var-from-fd-by-fd variable fd-to-catch fd-to-sacrifice command [args..]
catch-var-from-fd-by-fd()
{
local -n v="$1";
local fd1="$2" fd2="$3";
shift 3 || return;

eval exec "$fd2>&1";
v="$(eval '"$@"' "$fd1>&1" "1>&$fd2" "$fd2>&-")";
eval exec "$fd2>&-";
}

Lưu ý bảo mật:catch-var-from-fd-by-fd Không được lấy 3 đối số đầu tiên từ bên thứ 3. Luôn cung cấp cho họ một cách rõ ràng theo kiểu "tĩnh".

Vì vậy, không-không-không catch-var-from-fd-by-fd $var $fda $fdb $command, không bao giờ làm điều này!

Nếu bạn tình cờ chuyển vào một tên biến khác nhau, ít nhất hãy làm như sau: local -n var="$var"; catch-var-from-fd-by-fd var 3 5 $command

Điều này vẫn không bảo vệ bạn trước mọi khai thác, nhưng ít nhất là giúp phát hiện và tránh các lỗi script phổ biến.

Ghi chú:

  • catch-var-from-fd-by-fd var 2 3 cmd.. giống như catch-stderr var cmd..
  • shift || returnchỉ là một số cách để ngăn chặn các lỗi xấu trong trường hợp bạn quên đưa ra số lượng đối số chính xác. Có lẽ chấm dứt shell sẽ là một cách khác (nhưng điều này làm cho nó khó kiểm tra từ dòng lệnh).
  • Các thói quen đã được viết như vậy, nó là dễ hiểu hơn. Người ta có thể viết lại chức năng mà nó không cần exec, nhưng sau đó nó trở nên thực sự xấu xí.
  • Thói quen này có thể được viết lại cho không phải bashcũng như vậy mà không cần local -n. Tuy nhiên, sau đó bạn không thể sử dụng các biến cục bộ và nó trở nên cực kỳ xấu xí!
  • Cũng lưu ý rằng các evals được sử dụng một cách an toàn. Thường evalđược coi là nguy hiểm. Tuy nhiên trong trường hợp này, nó không tệ hơn việc sử dụng "$@"(để thực thi các lệnh tùy ý). Tuy nhiên, hãy chắc chắn sử dụng trích dẫn chính xác và chính xác như được hiển thị ở đây (nếu không nó sẽ trở nên rất nguy hiểm ).

3

Đây là cách tôi đã làm:

#
# $1 - name of the (global) variable where the contents of stderr will be stored
# $2 - command to be executed
#
captureStderr()
{
    local tmpFile=$(mktemp)

    $2 2> $tmpFile

    eval "$1=$(< $tmpFile)"

    rm $tmpFile
}

Ví dụ sử dụng:

captureStderr err "./useless.sh"

echo -$err-

không sử dụng một tập tin tạm thời. Nhưng ít nhất những thứ xấu xí được bọc trong một chức năng.


@ShadowWizard Ít nghi ngờ về phía tôi. Trong tiếng Pháp, dấu hai chấm thường đi trước một khoảng trắng. Tôi áp dụng sai quy tắc này với câu trả lời bằng tiếng Anh . Sau khi kiểm tra điều này , tôi biết tôi sẽ không phạm sai lầm này nữa.
Stephan

@Stephan chúc mừng, điều này cũng đã được thảo luận ở đây . :)
Shadow Wizard là tai cho bạn

1
Có nhiều cách an toàn hơn để làm điều này hơn là sử dụng eval. Chẳng hạn, printf -v "$1" '%s' "$(<tmpFile)"không có nguy cơ chạy mã tùy ý nếu TMPDIRbiến của bạn đã được đặt thành giá trị độc hại (hoặc tên biến đích của bạn chứa giá trị đó).
Charles Duffy

1
Tương tự, rm -- "$tmpFile"là mạnh mẽ hơn rm $tmpFile.
Charles Duffy

2

Đây là một vấn đề thú vị mà tôi hy vọng có một giải pháp tao nhã. Đáng buồn thay, tôi kết thúc với một giải pháp tương tự như ông Leffler, nhưng tôi sẽ nói thêm rằng bạn có thể gọi vô dụng từ bên trong hàm Bash để cải thiện khả năng đọc:

#! / bin / bash

chức năng vô dụng {
    /tmp/usless.sh | sed 's / Đầu ra / Vô dụng /'
}

LRI = $ (vô dụng)
tiếng vang $ LRI

Tất cả các loại chuyển hướng đầu ra khác phải được hỗ trợ bởi một tệp tạm thời.


2

POSIX

STDERR có thể được bắt giữ bằng một số phép thuật chuyển hướng:

$ { error=$( { { ls -ld /XXXX /bin | tr o Z ; } 1>&3 ; } 2>&1); } 3>&1
lrwxrwxrwx 1 rZZt rZZt 7 Aug 22 15:44 /bin -> usr/bin/

$ echo $error
ls: cannot access '/XXXX': No such file or directory

Lưu ý rằng đường ống STDOUT của lệnh (ở đây ls) được thực hiện bên trong cùng { }. Nếu bạn đang thực hiện một lệnh đơn giản (ví dụ, không phải là một đường ống), bạn có thể loại bỏ các dấu ngoặc trong này.

Bạn không thể đặt ống bên ngoài lệnh vì đường ống tạo ra một lớp con bashzshvà việc gán cho biến trong lớp con sẽ không khả dụng cho lớp vỏ hiện tại.

bash

Trong bashđó, tốt hơn là không cho rằng mô tả tệp 3 không được sử dụng:

{ error=$( { { ls -ld /XXXX /bin | tr o Z ; } 1>&$tmp ; } 2>&1); } {tmp}>&1; 
exec {tmp}>&-  # With this syntax the FD stays open

Lưu ý rằng điều này không hoạt động zsh.


Nhờ câu trả lời này cho ý tưởng chung.


bạn có thể giải thích dòng này với các chi tiết? không hiểu 1> & $ tmp; {error = $ ({{ls -ld / XXXX / bin | tr o Z;} 1> & $ tmp;} 2> & 1); } {tmp}> & 1;
Thiago Conrado

1

Bài đăng này đã giúp tôi đưa ra một giải pháp tương tự cho mục đích của riêng tôi:

MESSAGE=`{ echo $ERROR_MESSAGE | format_logs.py --level=ERROR; } 2>&1`

Sau đó, miễn là MESSAGE của chúng tôi không phải là một chuỗi trống, chúng tôi chuyển nó sang các thứ khác. Điều này sẽ cho chúng tôi biết nếu format_logs.py của chúng tôi không thành công với một loại ngoại lệ python.


1

Chụp và in stderr

ERROR=$( ./useless.sh 3>&1 1>&2 2>&3 | tee /dev/fd/2 )

Phá vỡ

Bạn có thể sử dụng $()để chụp stdout, nhưng thay vào đó bạn muốn chụp stderr. Vì vậy, bạn trao đổi stdout và stderr. Sử dụng fd 3 làm bộ lưu trữ tạm thời trong thuật toán trao đổi tiêu chuẩn.

Nếu bạn muốn chụp VÀ in sử dụng teeđể tạo một bản sao. Trong trường hợp này, đầu ra của teesẽ được ghi lại $()thay vì đi đến bàn điều khiển, nhưng stderr (of tee) vẫn sẽ chuyển đến bàn điều khiển để chúng tôi sử dụng nó làm đầu ra thứ hai cho teequa tệp đặc biệt /dev/fd/2teemong đợi một đường dẫn tệp chứ không phải là fd con số.

LƯU Ý: Đó là rất nhiều chuyển hướng khủng khiếp trong một dòng duy nhất và thứ tự quan trọng. $()đang nắm lấy thiết bị xuất phát teeở cuối đường ống và chính đường ống dẫn đường ./useless.shđến stdin của teeSAU, chúng tôi đã trao đổi stdin và thiết bị xuất chuẩn ./useless.sh.

Sử dụng thiết bị xuất chuẩn của ./usless.sh

OP cho biết ông vẫn muốn sử dụng thiết bị xuất chuẩn (không chỉ in), thích ./useless.sh | sed 's/Output/Useless/'.

Không có vấn đề chỉ cần làm điều đó TRƯỚC KHI trao đổi stdout và stderr. Tôi khuyên bạn nên chuyển nó vào một hàm hoặc tệp (cũng-không biết.sh) và gọi nó thay cho ./usless.sh trong dòng trên.

Tuy nhiên, nếu bạn muốn CAPTURE stdout AND stderr, thì tôi nghĩ rằng bạn phải quay lại các tệp tạm thời vì $()sẽ chỉ thực hiện một lần và nó tạo ra một nhánh con mà bạn không thể trả về các biến.


1

Lặp lại một chút về câu trả lời của Tom Hale, tôi đã thấy có thể bọc yoga chuyển hướng thành một chức năng để tái sử dụng dễ dàng hơn. Ví dụ:

#!/bin/sh

capture () {
    { captured=$( { { "$@" ; } 1>&3 ; } 2>&1); } 3>&1
}

# Example usage; capturing dialog's output without resorting to temp files
# was what motivated me to search for this particular SO question
capture dialog --menu "Pick one!" 0 0 0 \
        "FOO" "Foo" \
        "BAR" "Bar" \
        "BAZ" "Baz"
choice=$captured

clear; echo $choice

Gần như chắc chắn có thể đơn giản hóa điều này hơn nữa. Không được kiểm tra đặc biệt kỹ lưỡng, nhưng nó dường như hoạt động với cả bash và ksh.


0

Nếu bạn muốn bỏ qua việc sử dụng tệp tạm thời, bạn có thể sử dụng thay thế quy trình. Tôi vẫn chưa làm cho nó hoạt động được. Đây là nỗ lực đầu tiên của tôi:

$ .useless.sh 2> >( ERROR=$(<) )
-bash: command substitution: line 42: syntax error near unexpected token `)'
-bash: command substitution: line 42: `<)'

Sau đó tôi đã thử

$ ./useless.sh 2> >( ERROR=$( cat <() )  )
This Is Output
$ echo $ERROR   # $ERROR is empty

Tuy nhiên

$ ./useless.sh 2> >( cat <() > asdf.txt )
This Is Output
$ cat asdf.txt
This Is Error

Vì vậy, sự thay thế quá trình nói chung là điều đúng đắn ... thật không may, bất cứ khi nào tôi bọc STDIN bên trong >( )bằng một thứ gì đó trong $()nỗ lực nắm bắt điều đó với một biến, tôi sẽ mất nội dung của nó $(). Tôi nghĩ rằng điều này là do $()khởi chạy một quy trình phụ không còn có quyền truy cập vào bộ mô tả tệp trong / dev / fd do quy trình cha sở hữu.

Quá trình thay thế đã mua cho tôi khả năng làm việc với luồng dữ liệu không còn trong STDERR, thật không may là tôi dường như không thể điều khiển nó theo cách tôi muốn.


1
Nếu bạn đã làm ./useless.sh 2> >( ERROR=$( cat <() ); echo "$ERROR" )thì bạn sẽ thấy đầu ra của ERROR. Vấn đề là sự thay thế quá trình được chạy trong lớp vỏ phụ, vì vậy giá trị được đặt trong lớp vỏ phụ không ảnh hưởng đến lớp vỏ cha.
Jonathan Leffler

0
$ b=$( ( a=$( (echo stdout;echo stderr >&2) ) ) 2>&1 )
$ echo "a=>$a b=>$b"
a=>stdout b=>stderr

3
Điều này có vẻ là một ý tưởng tốt, nhưng trên Mac OSX 10.8.5, nó được ina=> b=>stderr
Heath

3
Tôi đồng ý với @HeathBnings; Điều này không tạo ra đầu ra được hiển thị. Vấn đề ở đây là ađược đánh giá và gán trong một vỏ con và việc gán trong vỏ con không ảnh hưởng đến vỏ cha. (Đã thử nghiệm trên Ubuntu 14.04 LTS cũng như Mac OS X 10.10.1.)
Jonathan Leffler

Điều tương tự trong Windows GitBash. Vì vậy, nó không hoạt động. ( GNU bash, version 4.4.12(1)-release (x86_64-pc-msys))
Kirby

Không hoạt động trên SLE 11.4một trong hai và tạo ra hiệu ứng được mô tả bởi
@JonathanLeffler

Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
β.εηοιτ.βε

0

Trong zsh:

{ . ./useless.sh > /dev/tty } 2>&1 | read ERROR
$ echo $ERROR
( your message )

0

Để kiểm tra lỗi các lệnh của bạn:

execute [INVOKING-FUNCTION] [COMMAND]

execute () {
    function="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${function}: ${error}"
        exit 1
    fi
}

Lấy cảm hứng trong sản xuất Lean:


Các giải pháp thành ngữ là mở ra sự phân công bên trong if. Hãy để tôi đăng một giải pháp riêng biệt.
tripleee


0

Cải thiện câu trả lời của YellowApple :

Đây là hàm Bash để bắt stderr vào bất kỳ biến nào

stderr_capture_example.sh:

#!/usr/bin/env bash

# Capture stderr from a command to a variable while maintaining stdout
# @Args:
# $1: The variable name to store the stderr output
# $2: Vararg command and arguments
# @Return:
# The Command's Returnn-Code or 2 if missing arguments
function capture_stderr {
  [ $# -lt 2 ] && return 2
  local stderr="$1"
  shift
  {
    printf -v "$stderr" '%s' "$({ "$@" 1>&3; } 2>&1)"
  } 3>&1
}

# Testing with a call to erroring ls
LANG=C capture_stderr my_stderr ls "$0" ''

printf '\nmy_stderr contains:\n%s' "$my_stderr"

Kiểm tra:

bash stderr_capture_example.sh

Đầu ra:

 stderr_capture_example.sh

my_stderr contains:
ls: cannot access '': No such file or directory

Hàm này có thể được sử dụng để nắm bắt lựa chọn trả về của dialoglệnh.

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.