問題
給定一個 BASH 管道:
./a.sh | ./b.sh
PID 為./a.sh10。
有沒有辦法./a.sh從內部找到PID ./b.sh?
即如果有,如果./b.sh看起來像下面這樣:
#!/bin/bash
...
echo $LEFT_PID
cat
那么輸出./a.sh | ./b.sh將是:
10
... Followed by whatever else ./a.sh printed to stdout.
背景
我正在處理這個名為 bash 的腳本,cachepoint我可以將它放在管道中以加快速度。
例如 cat big_data | sed 's/a/b/g' | uniq -c | cachepoint | sort -n
這是一個有意為之的簡單示例。
管道一開始可能運行緩慢,但在后續運行中,隨著cachepoint開始作業,它會更快。
我cachepoint想象的作業方式是它會使用前幾百行輸入,以及它之前的命令串列,以便為先前快取的資料形成一個哈希 ID,從而在后續運行中盡早破壞 stdin 管道,而是求助于列印快取的資料。快取資料每隔一小時左右就會被洗掉一次。
即| cachepoint,在正常情況下,剩下的所有內容都將繼續運行,可能會運行到 1,000,000 行,但在cachepoint管道的后續執行中,| cachepoint可能會在 100 行后退出,并且cachepoint會簡單地列印它已快取的數百萬行。對于管道源和管道內容的哈希,我需要一種方法cachepoint來讀取管道中它之前的 PID。
我經常使用管道來探索資料集,而且我經常發現自己通過管道傳輸到臨時檔案,以繞過多次重復相同的昂貴管道。這很亂,所以我想要cachepoint。
uj5u.com熱心網友回復:
這個Shellcheck -clean 代碼應該適用b.sh于任何 Linux 系統上的程式:
#! /bin/bash
shopt -s extglob
shopt -s nullglob
left_pid=
# Get the identifier for the pipe connected to the standard input of this
# process (e.g. 'pipe:[10294010]')
input_pipe_id=$(readlink "/proc/self/fd/0")
if [[ $input_pipe_id != pipe:* ]]; then
echo 'ERROR: standard input is not a pipe' >&2
exit 1
fi
# Find the process that has standard output connected to the same pipe
for stdout_path in /proc/ ([[:digit:]])/fd/1; do
output_pipe_id=$(readlink -- "$stdout_path")
if [[ $output_pipe_id == "$input_pipe_id" ]]; then
procpid=${stdout_path%/fd/*}
left_pid=${procpid#/proc/}
break
fi
done
if [[ -z $left_pid ]]; then
echo "ERROR: Failed to set 'left_pid'" >&2
exit 1
fi
echo "$left_pid"
cat
- 這取決于這樣一個事實:在 Linux 上,對于 id 為 PID 的行程,路徑
/proc/PID/fd/0看起來像是連接到行程標準輸入/proc/PID/fd/1的設備的符號鏈接,看起來像是連接到行程標準輸出的設備的符號鏈接。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/373049.html
