Bash

將密碼 (cat) 傳遞給 sed 以替換配置值

  • March 19, 2021

我有一個名為的配置文件.env,其中包含:

DB_PASSWORD={password}

我們有一個MySQL /root/.mysql/db00.yml.dbroot 帳戶的密碼。我正在嘗試將其導入sed以下內容:

cat /root/.mysql/db00.yml.db | sed -i -e "s/DB_PASSWORD=/DB_PASSWORD=(.*)/g" .env

沒有任何運氣,嘗試了一些變化,例如:

sed -i "s/DB_PASSWORD=/DB_PASSWORD=$(cat /root/.mysql/db00.yml.db)" .env
mysqlpwd=$(cat /root/.mysql/db00.yml.db)
# Use the variable in sed -i
sed -i "s/DB_PASSWORD=/DB_PASSWORD=$mysqlpwd/g" .env

這會產生錯誤:

root@linuxbox:/var/www/www.example.com# mysqlpwd=$(cat /root/.mysql/db00.yml.db)
root@linuxbox:/var/www/www.example.com# sed -i "s/DB_PASSWORD=/DB_PASSWORD=$mysqlpwd/g" .env
sed: -e expression #1, char 33: unknown option to `s'

更新:

不執行它/g也會失敗:

root@linuxbox:/var/www/www.example.com# echo $mysqlpwd
Rjcr/Sn+s/a2QbGx
root@linuxbox:/var/www/www.example.com# cat .env | grep DB_PASSWORD
DB_PASSWORD=(.*)()
root@linuxbox:/var/www/www.example.com# sed -i "s/DB_PASSWORD=/DB_PASSWORD=$mysqlpwd/" .env
sed: -e expression #1, char 33: unknown option to `s'

這些方法似乎都不起作用。

我正在跑步sed 4.7,即:

root@linuxbox:/var/www/www.example.com# sed --version
sed (GNU sed) 4.7

嘗試為 sed 使用不同的分隔符…根據您的實際密碼(例如,如果它包含*|&\1*),仍然存在失敗的風險。

sed -i "s|DB_PASSWORD=|DB_PASSWORD=$mysqlpwd|" .env

就其本質而言,必須允許密碼包含任何可由鍵盤可靠生成的字元。這意味著密碼可以很容易地包含有效sed程式碼或字元串,這些程式碼或字元串在註入sed編輯腳本時會破壞該腳本,寫入系統上的任意文件,或者使用 GNUsed執行任意命令(當您以根,你似乎是)。

sed當您需要使用使用者提供的數據時不要使用,除非您確切知道如何清理它。我個人會避免sed任何需要我對sed錶達式進行雙引號(而不是單引號)以允許 shell 擴展我幾乎無法控制的變數的事情。

相反,使用awk

awk -F '=' '
   BEGIN { OFS = FS }
   NR == FNR { password = $0; next }
   $1 == "DB_PASSWORD" { sub("=.*",""); $2 = password }; 1' /root/.mysql/db00.yml.db .env >.env.new &&
mv .env.new .env

這首先從第一個文件的第一行讀取密碼(假設這僅包含帶有逐字密碼的單行)。

然後它將您的.env文件視為 -=分隔欄位的文件。

當一行的第一個欄位是DB_PASSWORD時,它會清除該行第一個欄位之後的所有內容=(以防舊密碼包含=),並將密碼作為第二個欄位插入。

所有行,無論是否修改,都輸出到.env.new,然後該文件將舊的替換.envmv

至關重要的是,我從不將從這兩個文件中的任何一個讀取的數據用作程序中的程式碼awk,並且我從不允許awk將密碼的任何部分視為特殊的。請注意,在呼叫中使用密碼作為替換字元串sub()會有問題,因為這會將&字元串中的任何字元串視為特殊字元串。

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