コマンドが失敗した場合、GNU awk ERRNOは設定されません。

コマンドが失敗した場合、GNU awk ERRNOは設定されません。

getline()awkGNU関数を使用していくつかのコマンドを実行し、返されたエラー番号()の値を印刷しようとしていますerrno。ただし、存在しないディレクトリ/ファイルの単純な失敗ケースの場合、変数は埋められないようです。

awk 'BEGIN {
        cmd = "ls -lrth /non/existing/path"
        while ( ( cmd | getline result ) > 0 ) {
            print result
        }
        close(cmd); print ENVIRON["ERRNO"]
}'

lsこのステートメントは、上記のエラー文字列が出力されたときにprint有効なエラー番号を生成しません。私もマニュアルページ使用PROCINFO["errno"]してPROCINFO["ERRNO"]動作しないこと。ファイルを閉じる前にファイル記述子を印刷してみましたが、やはり機能しませんでした。ENOENTこの場合、期待は間違っていますか?

答え1

を使用してエラー番号を取得できませんgetline。コマンドでは、出力はでlsはなく出力されますprint result

フォームで実行され、次のcmd | getline result出力cmdがにパイプされますgetline1出力がある場合は返し、0失敗した場合はEOFを返します-1。問題は、失敗が実行自体のためではgetlineありませんcmd

awk 'BEGIN {
while ( ( getline result < "/etc/shadow") > 0 ) {
            print result
        }
        print "XXX: ", ERRNO
}'
XXX:  Permission denied

/etc/shadow読み取れないためgetline実行できず、変数エラーが報告されていることがわかりますERRNO


cmdGNU awk は posix モードでない場合は状態を返すので、次のことができます。

awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    status=close(cmd);
    if (status != 0) {
        code=and(rshift(status, 8),0xFF)
        printf("Exit status: %d, exit code: %d\n", status, code)
    }
}'
ls: cannot access '/non/existing/path': No such file or directory
Exit status: 512, exit code: 2

POSIX モードでは終了状態を取得できません。

POSXILY_CORRECT=1 awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    status=close(cmd);
    if (status != 0) {
        code=and(rshift(status, 8),0xFF)
        printf("Exit status: %d, exit code: %d\n", status, code)
    }
}'
ls: cannot access '/non/existing/path': No such file or directory

答え2

ERRNOはgawkにのみ設定できます(GNU awkただ)getlineまたはcloseが失敗しますが、lsの(空の!)出力を正常に読み取る場合です。 lsは標準エラーチャネル(「ls:アクセスできません...」)にエラーメッセージを表示し、標準出力に何も書き込まず、エラーコードがあるため出力が空です。

GNU awkを使用すると、次のコマンドの終了ステータスを取得できます。

exitstatus=close(cmd)
if (exitstatus) {
    # do something
}

コマンドのエラーメッセージが必要な場合は、標準エラーチャネルをいくつかのファイルにリダイレクトして読み取る必要があります。

awk 'BEGIN {
    cmd = "ls -lrth /non/existing/path 2>standard-error.txt"
    while ( ( cmd | getline result ) > 0 ) {
        print result
    }
    es=close(cmd);
    if (es) {
        getline errstring < "standard-error.txt"
        print "exitstatus "es" error message "errstring;
    }
}'

関連情報