テキストベースの構成ファイルにカスタム構成を自動的に適用するスクリプトを作成したいと考えています。
今回のケースでは、/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"
'
しかし、私はそれをお勧めしません。