この行がまだファイルの一部でない場合にのみファイルに行を挿入する

この行がまだファイルの一部でない場合にのみファイルに行を挿入する

テキストベースの構成ファイルにカスタム構成を自動的に適用するスクリプトを作成したいと考えています。

今回のケースでは、/etc/sysctl.confこれらの行がまだファイル内に存在しない場合に 2 行を追加しようとしています (ファイル内にこれらの行が複数回出現するのを避けるため)。

私が使用するスクリプトは次のとおりです:

if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
echo vm.vfs_cache_pressure=50 | sudo tee -a /etc/sysctl.conf
fi
if [ `grep vm.vfs_cache_pressure /etc/sysctl.conf` != "vm.vfs_cache_pressure=50" ]; then
echo vm.vfs_cache_pressure=50 | sudo tee -a /etc/sysctl.conf
fi

そして、次のようなエラーが発生します:

/home/erwan/Workspace/Install.sh: ligne 19 : [: != : opérateur unaire attendu
/home/erwan/Workspace/Install.sh: ligne 23 : [: != : opérateur unaire attendu

何が間違っているのでしょうか?

答え1

これは問題だ:

if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then

if はgrep何も見つからないため、何も出力されず、この左側には何も表示されず、エラーになります。何か見つかった場合も、出力に空白が含まれる可能性があるため、問題になります (たとえば、if がvm.swappinessファイル内に複数回存在する場合)。これは引用符で囲む必要があります。そうしないと、展開時に一連の異なる文字列として表示されます。

したがって、出力が引用符で囲まれるように を使用する必要がありますif [ "$(grep ...)" ]。出力がない場合は となり、""これは bash のテストのどちらの側でも問題ありません。

しかし、この場合は、終了ステータスgrep の代わりにman grep

終了ステータス

通常、選択された行が見つかった場合の終了ステータスは 0 で、そうでない場合は 1 です。ただし、エラーが発生した場合の終了ステータスは 2 です...

ここでも便利なのが-qスイッチです:

-q、--quiet、--silent

標準出力に何も書き込まない。すぐに終了するステータスゼロエラーが検出された場合でも、一致が見つかった場合は、

$?したがって、最後に完了したフォアグラウンド プロセスの終了ステータスに留意してください。

grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then

grep何も見つからず、エラーも発生しなかった場合、この条件は true になります。

答え2

何も返さないことが原因である可能性がありますgrep。引用符で囲まれていないため、エラー メッセージが表示されます (単項演算子が必要です)。次を試してください:-

if [ "$(grep vm.swappiness /etc/sysctl.conf)" != "vm.swappiness=5" ]; then

答え3

インスピレーション目的のためだけに、少し調整が必要かもしれません:

#assuming there is only one line with vm.swappiness
#otherwise you can use the test command with "grep -c vm.swappiness" first
#tests if the correct line is in the file
if grep -q -E '^vm.swappiness=5$' /etc/sysctl.conf; then
    echo "all good, do nothing";
else
    echo "removing possible lines with vm.swappiness"
    sudo sed -i '/^vm.swappiness=/d' /etc/sysctl.conf 
    echo "adding line with correct swappiness"
    sudo bash -c "echo 'vm.swappiness=5' >> /etc/sysctl.conf"
fi

また、これを関数でラップすると、次のパラメータでも呼び出せるので良いでしょう。

答え4

これはおそらくうまくいくでしょう:

f=/etc/sysctl.conf
[ -w "$f" ] || exit 1
for line in 'vm.swappiness=5' 'vm.vfs_cache_pressure=50' ; do
    grep -q "$line" <"$f" || printf %s\\n "$line"
done >>"$f"

おそらくそのスクリプトも終了したほうがよいでしょうsudo。必要な場合はスクリプトを実行してください sudoのようにしてsudo ./script.sh、他のスクリプトとは別のモジュールとして保持します。そうでない場合は、次のようにします。

sudo sh -c '
    f=/etc/sysctl.conf
    [ -w "$f" ] || exit 1
    for line in "vm.swappiness=5" "vm.vfs_cache_pressure=50" ; do
        grep -q "$line" <"$f" || printf %s\\n "$line"
    done >>"$f"
'

しかし、私はそれをお勧めしません。

関連情報