我正在寻找创建一个脚本来自动将一些自定义配置应用于基于文本的配置文件。
在目前的情况下,我正在搜索添加 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
因为如果grep
找不到任何东西,它不会输出任何东西,并且它的左边什么也不会,这是一个错误。如果它确实找到了某些东西,这也是一个问题,因为输出可能包含空格(例如,如果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"
'
但我不推荐它。