以下を含む構成ファイルがあります.env
。
DB_PASSWORD={password}
その中には/root/.mysql/db00.yml.db
MySQL rootアカウントのパスワードがあります。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
答え1
本質的に、パスワードは以下を許可する必要があります。キーボードが安定して生成できるすべての文字。これは、編集スクリプトsed
に挿入されたときにスクリプトをsed
破損したり、システム上の任意のファイルに書き込んだり、GNUを使用して任意のコマンドを実行したりするための有効なコードまたは文字列をパスワードに簡単に含めることができることを意味しますsed
(ルートとして実行すると)。
ユーザー提供のデータを使用する必要がある場合は、sed
データを整理する方法を正確に知らない限り使用しないでください。私は、シェルが私がほとんど制御できない変数を拡張できるように、二重引用符式(一重引用符の代わりに)を必要とするsed
すべてを避けたいと思います。sed
代わりに、以下を使用してください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
最初のファイルの最初の行からパスワードを読むことから始めます(ファイルにパスワードがそのまま含まれる1行だけが含まれているとします)。
次に、ファイルを.env
区切りフィールドで構成されたファイルとして扱います。=
行の最初のフィールドがある場合は、DB_PASSWORD
行の最初のフィールド=
の後のすべての項目を消去し(以前のパスワードが含まれている場合=
)、パスワードを2番目のフィールドに挿入します。
変更するかどうかにかかわらず、すべての行がとして出力され、ファイルは.env.new
前の行.env
に置き換えられますmv
。
決定的に、私は2つのファイルから読み取ったデータを次のように使用しません。パスワード私のプログラムでは、パスワードのどの部分も特別に扱うことを決してawk
許可しません。awk
呼び出し時に代替文字列としてパスワードを使用すると、sub()
問題が発生する可能性があります。これは、&
文字列のすべての内容が特殊文字列として扱われるためです。
答え2
sedで別の区切り文字を試してください...実際のパスワードによってはまだ失敗する危険があります(例:|または&または\1)。
sed -i "s|DB_PASSWORD=|DB_PASSWORD=$mysqlpwd|" .env
答え3
コマンドライン引数にパスワードを入力しないでください。システム内のすべてのユーザーが、1つps
以上top
の他の方法でパスワードを読み取ることができます。一部の自動化シナリオでは、これは可能性が低い可能性があることを知っています(誰もボックスにログインする可能性がないため)。しかし、それはまだ悪い考えであり、いくつかの監視ツールや他の人のいくつかのスクリプトがログに発生する可能性が常にあります。特定の時点でシステム上で実行されているプロセスを実行して、どこにいるかを知っている人にパスワードを記録します。
を使用して素晴らしい答えを得ました。共有に使用するawk
簡単なソリューションも作成しました。ex
これは特殊文字を含むすべてのパスワードに適用されます。唯一の例外は次のとおりです。終わりバックスラッシュで。
ファイルに以下が.env
含まれている場合:
somevar1=someval
somevar2=some other val
DB_PASSWORD=
somevar3=another val
somevar4=val
以下myscript
を含みます。
/^DB_PASSWORD=$/a
!@#$#% some complicated password "^$%^&@#,.,cmxz\k'dvok][
.
0//j!
x
ただ実行すると、ex .env < myscript
次のような結果が得られます。
$ ex .env < myscript
$ cat .env
somevar1=someval
somevar2=some other val
DB_PASSWORD=!@#$#% some complicated password "^$%^&@#,.,cmxz\k'dvok][
somevar3=another val
somevar4=val
$
答え4
sed -i -e "
/^DB_PASSWORD=/c\\
DB_PASSWORD=$(sed -e 's:[\\]:&&:g' /root/.mysql/db00.yml.db)
" ./.env
- 変更コマンドに挿入された値を確保するために、sedコード自体にパスワード削除機能を組み込んでいます。
c\