Estou procurando criar um script para aplicar automaticamente algumas configurações personalizadas a arquivos de configuração baseados em texto.
No presente caso, estou procurando adicionar 2 linhas /etc/sysctl.conf
se essas linhas ainda não estiverem no arquivo (para evitar ocorrências múltiplas dessas linhas no arquivo).
aqui está o script que eu uso:
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
e o erro que recebo:
/home/erwan/Workspace/Install.sh: ligne 19 : [: != : opérateur unaire attendu
/home/erwan/Workspace/Install.sh: ligne 23 : [: != : opérateur unaire attendu
O que estou fazendo de errado?
Responder1
Isto é um problema:
if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
Como if grep
não encontra nada, não gera nada, e o lado esquerdo disso não será nada, o que é um erro. Também é um problema se encontrar algo, já que a saída pode conter espaços em branco (por exemplo, se vm.swappiness
estiver no arquivo várias vezes). Isso precisa ser citado ou aparecerá como uma série de strings distintas quando expandido.
Você deve, portanto, usar if [ "$(grep ...)" ]
para que a saída seja citada. Se não houver saída, você tem ""
, o que é bom em ambos os lados de um teste no bash.
No entanto, neste caso eu recomendo usar ostatus de saídado grep em vez disso. De man grep
:
ESTADO DE SAÍDA
Normalmente, o status de saída é 0 se as linhas selecionadas forem encontradas e 1 caso contrário. Mas o status de saída é 2 se ocorreu um erro...
Também útil aqui é a -q
opção:
-q, --quiet, --silent
Quieto; não escreva nada na saída padrão. Saia imediatamentecom status zerose alguma correspondência for encontrada, mesmo que um erro tenha sido detectado.
Portanto, tenha em mente $?
o status de saída do último processo em primeiro plano concluído:
grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then
Esta condição será verdadeira se grep
não for encontrado nada e nenhum erro ocorreu.
Responder2
Pode ser porque você grep
não está retornando nada. Como não está entre aspas, você recebe essa mensagem de erro (operador unário esperado). Tentar:-
if [ "$(grep vm.swappiness /etc/sysctl.conf)" != "vm.swappiness=5" ]; then
Responder3
Apenas para fins de inspiração, talvez precise de alguns ajustes:
#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
Também envolver isso em uma função pode ser bom, então você também pode chamá-lo com seu próximo parâmetro.
Responder4
Isso provavelmente funcionaria:
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"
Você provavelmente deveria sair sudo
desse script também. Se necessário execute o scriptcom sudo
like sudo ./script.sh
e mantenha-o como um módulo separado de outros scripts. Caso contrário, faça:
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"
'
Mas eu não recomendo.