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

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

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.confse 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 grepnã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.swappinessestiver 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 -qopçã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 grepnão for encontrado nada e nenhum erro ocorreu.

Responder2

Pode ser porque você grepnã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 sudodesse script também. Se necessário execute o scriptcom sudolike sudo ./script.she 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.

informação relacionada