Inserindo uma linha em um arquivo somente se esta linha ainda não fizer parte do arquivo

2

Estou procurando criar um script para aplicar automaticamente alguma configuração personalizada a arquivos de configuração baseados em texto.

No presente caso, estou procurando adicionar 2 linhas a /etc/sysctl.conf se essas linhas ainda não estiverem no arquivo (para evitar a ocorrência múltipla 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?

    
por Dremor 23.06.2014 / 16:27

4 respostas

6

Isso é um problema:

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

Como se grep não encontrar nada, ele não produzirá nada, e o lado esquerdo disso não será nada, o que é um erro. Também é um problema se encontrar algo, pois a saída pode conter espaço 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.

Portanto, você deve usar if [ "$(grep ...)" ] para que a saída seja citada. Se não houver saída, você terá "" , o que é bom em ambos os lados de um teste no bash.

No entanto, neste caso, recomendo usar o status de saída do grep. De man grep :

EXIT STATUS

Normally, the exit status is 0 if selected lines are found and 1 otherwise. But the exit status is 2 if an error occurred...

Também é útil aqui a opção -q :

-q, --quiet, --silent

Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected.

Portanto, tenha em mente que $? é o status de saída do último processo de 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 encontrar nada e nenhum erro ocorrer.

    
por 23.06.2014 / 16:48
4

Pode ser porque o seu grep não está retornando nada. Como não é citado, você recebe essa mensagem de erro (operador unário esperado). Tente: -

if [ "$(grep vm.swappiness /etc/sysctl.conf)" != "vm.swappiness=5" ]; then
    
por 23.06.2014 / 16:49
3

Apenas para fins de inspiração, precisa de alguns ajustes, talvez:

#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

Envolver isso em uma função pode ser bom, então você pode chamar com o próximo parâmetro também.

    
por 24.06.2014 / 02:39
0

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 também deve receber sudo desse script. Se necessário, execute o script com sudo como sudo ./script.sh e mantenha-o como um módulo separado de outros scripts. Outra coisa:

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 isso.

    
por 23.06.2014 / 17:38