Bash

將函式和變數轉發到 sudo su - <user> <<EOF

  • August 27, 2018

我已經在 bash/ksh 中聲明了函式和變數,我需要將它們轉發到sudo su - {user} &lt;&lt; EOF

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - &lt;user&gt; &lt;&lt; EOF
 intVAR=$(date)
 log_f ${intVAR} ${extVAR}
EOF

sudo su -,這是一種複雜的寫作方式sudo -i,建構了一個原始的環境。這就是登錄外殼的意義所在。即使是普通的,也會sudo從環境中刪除大多數變數。此外sudo是一個外部命令;沒有辦法提升 shell 腳本本身的權限,只能執行sudo具有額外權限的外部程序 ( ),這意味著父 shell 中定義的任何 shell 變數(即非導出變數)和函式在子殼。

您可以通過不呼叫登錄 shell(sudo bash而不是sudo su -or sudo -i)並配置 sudo 讓這些變數通過(在文件中使用Defaults !env_resetor )來傳遞環境變數。這對函式沒有幫助(儘管 bash 有函式導出工具,但 sudo 會阻止它)。Defaults env_keep=…``sudoers

在子 shell 中獲取函式的正常方法是在那裡定義它們。注意引用:如果你使用&lt;&lt;EOFhere文件,here文件的內容首先被父shell擴展,擴展的結果成為子shell看到的腳本。也就是說,如果你寫

sudo -u "$target_user" -i &lt;&lt;EOF
echo "$(whoami)"
EOF

這將顯示原始使用者的名稱,而不是目標使用者的名稱。為避免第一階段的擴展,請在&lt;&lt;操作符後引用 here 文件標記:

sudo -u "$target_user" -i &lt;&lt;'EOF'
echo "$(whoami)"
EOF

因此,如果您不需要將數據從父 shell 傳遞到子 shell,則可以使用這裡引用的文件:

#!/bin/bash
sudo -u "$target_user" -i  &lt;&lt;'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

雖然您可以使用此處未引用的文件標記將數據從父 shell 傳遞到子 shell,但這僅在數據不包含任何特殊字元時才有效。那是因為在像這樣的腳本中

sudo -u "$target_user" -i &lt;&lt;EOF
echo "$(whoami)"
EOF

的輸出whoami變成了一些 shell 程式碼,而不是字元串。例如,如果whoami命令返回"; rm -rf /; "true,則子 shell 將執行命令echo ""; rm -rf /; "true"

如果您需要從父 shell 傳遞數據,一種簡單的方法是將其作為參數傳遞。顯式呼叫子 shell 並將位置參數傳遞給它:

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh  _ "$extVAR" &lt;&lt;'EOF'
 log_f() {
 echo "LOG line: $@"
 }
 intVAR=$(date)
 log_f "${intVAR}" "${1}"
EOF

如果要傳遞多個變數,則按名稱傳遞它們會更易讀。顯式呼叫env以設置子 shell 的環境變數。

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh &lt;&lt;'EOF'
 log_f() {
 echo "LOG line: $@"
 }
 intVAR=$(date)
 log_f "${intVAR}" "${1}"
EOF

請注意,如果您希望讀取/etc/profile目標使用者~/.profile,則必須明確讀取它們,或者呼叫bash --login而不是呼叫sh.

引用自:https://unix.stackexchange.com/questions/175415