SIGPIPE 由於文件描述符和進程替換 (SIGPIPE due to file descriptors and process substitution)


問題描述

SIGPIPE 由於文件描述符和進程替換 (SIGPIPE due to file descriptors and process substitution)

我正在嘗試從執行工具的 bash 函數中保存一些日誌(其中一些在子 shell 中運行)。此外,我想將所有錯誤打印到終端。

我的代碼在點擊 ctr‑c 和一個奇怪的日誌文件時會導致一個 sigpipe 和退出代碼 141。管道失敗似乎是由陷阱內的 stdout 重定向到 stderr 引起的,這會破壞 tee 命令的 stdout 流。有趣的是,代碼按預期終止,退出代碼為 130,沒有在陷阱或 cat 命令中使用重定向。

  1. 我仍然無法修復和解釋生成的日誌文件。為什麼會有兩次迴聲,為什麼陷阱迴聲也會寫入文件?

  2. 為什麼沒有


    參考解法

    方法 1:

    The source of the SIGPIPE is that the SIGINT (initiated by ctrl/c) is sent to ALL processes running: both the "main" bash process (executing the 'fun' function), and the sub shell executing the 'tee ‑a'. As a result, on Ctrl/C, both get killed. When the main process tries to send 'trap_stderr' to te "tee" process, it get SIGPIPE, because the "tee" has already died.

    Given the role of the 'tee ‑a', it make sense to protect it from the SIGINT, and allow it to run until 'fun' complete (or killed). Consider the following change to the last line

    fun >> log 2> >(trap '' INT ; tee ‑a log >&2)
    

    which will produce the log file:

    Console (stderr)
    fun_stderr
    ^Ctrap_stderr
    
    Log File: (no duplicates)
    
    fun_stdout
    fun_stderr
    trap_stdout
    trap_stderr
    

    The above will also address the second question is about duplicate lines in the log file. This is the result of using tee to send each stderr line to log file AND stdout. Given that stdout just got redirect (by the '>>log') to the 'log' file, both copy of the output are sent to the log file, and none to the terminal

    Given the redirection are performed sequentially, changing the 'tee' line to sent the output to the original stderr (instead of the already redirect stdout) will show the output on the terminal (or whatever stderr is)

    方法 2:

    Why are there some echos twice


    </blockquote>

    fun's stdout is redirected to log before its stderr is redirected to the FIFO created for tee, thus tee inherits a stdout that is redirected to log. I can prove that like so:

    $ : > file 2> >(date)
    $ cat file
    Sat Jul 25 18:46:31 +03 2020
    

    Changing the order of redirections will fix that. E.g.:

    fun 2> >(tee ‑a log) >> log
    

    and why are the trap echos written to the file as well?

    If the trap set for SIGINT is triggered while the shell is still executing fun, its perfectly normal that the redirections associated with fun takes effect.

    To connect the trap action's stdout and stderr to those of the main shell, you can do:

    exec 3>&1 4>&2
    
    handler() {
      : # handle SIGINT here
    } 1>&3 2>&4
    
    trap handler INT
    

    Or something alike; the idea is making copies of the main shell's stdout and stderr.

    Why isn't the sigpipe caused earlier by the redirection within the function?

    Because tee is alive while echo fun_stderr >&2 is being executed. And sleep does not write anything to its stdout, so it can not trigger a SIGPIPE.

    The reason why this script terminates due to a SIGPIPE is that tee receives the SIGINT generated by the keyboard as well and terminates before the trap action associated with SIGINT is executed. As a result, while executing echo trap_stderr >&2, since its stderr is connected to a pipe that has been closed moments ago, the shell receives the SIGPIPE.

    To avoid this, as already suggested, you can make tee ignore SIGINT. You don't need to set an empty trap for that though, the ‑i option is enough.

    fun 2> >(tee ‑a ‑i log) >> log
    

    (by pyr0dash‑ooguz ismail)

    參考文件

    1. SIGPIPE due to file descriptors and process substitution (CC BY‑SA 2.5/3.0/4.0)

#file-descriptor #bash-trap #bash #process-substitution






相關問題

在 Android 中持久化文件描述符 (Persisting File Descriptors in Android)

無法理解 select() 系統調用 (failure to understand select() system call)

文件描述符中實際存儲了多少信息? (How much information is actually stored in a file descriptor?)

為同一個文件描述符創建兩個文件是否定義明確? (Is creating two FILEs for the same file descriptor well-defined?)

Android文件描述符洩漏調試 (Android file descriptor leakage debuging)

C中的文件描述符分配 (File Descriptor Assignment in C)

在某些 linux 程序中關閉奇怪的描述符 (Strange descriptor closing in some linux programs)

c read() 導致錯誤的文件描述符錯誤 (c read() causing bad file descriptor error)

C中系統調用的文件句柄問題 (Filehandle issue with system call in C)

使用 copy_file_range 進行複制加速 (Copy acceleration with copy_file_range)

打開文件過多錯誤,但 99.5% 的 inode 是免費的 (Too many open files error but 99.5% inodes are free)

SIGPIPE 由於文件描述符和進程替換 (SIGPIPE due to file descriptors and process substitution)







留言討論