Я пытаюсь создать скрипт для автоматического применения некоторых пользовательских настроек к текстовым файлам конфигурации.
В данном случае я ищу возможность добавить 2 строки, /etc/sysctl.conf
если этих строк еще нет в файле (чтобы избежать многократного появления этих строк в файле).
Вот скрипт, который я использую:
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, --тихий, --тихий
Тихо; ничего не писать в стандартный вывод. Выйти немедленнос нулевым статусомесли найдено какое-либо совпадение, даже если была обнаружена ошибка.
Итак, следует помнить $?
о статусе завершения последнего завершенного процесса переднего плана:
grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then
Это условие будет истинным, если grep
ничего не найдено и не произошло ошибки.
решение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"
'
Но я не рекомендую этого делать.