在子 shell 中引用外部腳本

/etc/X11/Xsession.d/ 裡的腳本, 都要注意使用的變數,因為要改變原本 Xsession 的行為, 是 source 執行的,但也因此使用的變數都會傳到外面。 在子 shell () 內引用就可以避免這個問題, 如果有需要匯出的,就再 $() echo 出來 eval 即可。

xsession

xsession.d 裡的腳本都是被 source 執行, 因為我沒有要匯出的變數,為了防止汙染 xsession, 我是把整個腳本包在 () 裡。

在子 shell 內 source

有時是想引用某腳本,但想要腳本執行完後再做一些事, 就能用在子 shell 內 source 的型式:

# 防止變數汙染
(
    . /some/script
    # 這裡看得到 script 裡的變數
    # 也看得到 () 外的變數

    git pull $some_var_in_script
    # do what ever you want to after script
)
# 在括號內的變數不會跑到括號外

大括號用途

小括號是子 shell,大括號則只是一般的代碼塊, 唯一用處就是,你需要把一堆命令模擬成一個命令時。

把一堆命令一起丟到背景

{
    sleep 30m
    zenity --info --text 眼睛該休息囉!
} &

把一堆命令模擬成一個

{
    echo '<pre>'
    cat file
    echo '</pre>'
} | w3m

結尾分號

但要注意,右大括號前的最後一個命令, 需要有分號或換行,和小括號不同。

if ( ps aux | grep tor ) # ok
then echo tor work!
fi
if { ps aux | grep tor; } # need semicolon
then echo tor work!
fi

其實這例子不需要括號的。 除非需要多個命令, 用最後一個當返回值,那可以用大括號。 如果判斷內還用到變數, 那可能要用小括號避免汙染。

將小括號內的變數引到外部

小括號外加 $ 就能取得內部的 stdout, 所以只要 echo 出要匯出的變數即可。

$(
    . /some/script
    echo some_var=$some_var
)
# export 為環境變數
export $(
    . /some/script
    echo some_var=$some_var
)

我在用 profile 就是這樣重用 /etc/X11/Xsession.d/90gpg-agent 的。