Estoy buscando crear un script para aplicar automáticamente alguna configuración personalizada a archivos de configuración basados en texto.
En el presente caso, estoy buscando agregar 2 líneas /etc/sysctl.conf
si estas líneas aún no están en el archivo (para evitar que estas líneas aparezcan varias veces en el archivo).
Aquí está el script que 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
y el error me sale:
/home/erwan/Workspace/Install.sh: ligne 19 : [: != : opérateur unaire attendu
/home/erwan/Workspace/Install.sh: ligne 23 : [: != : opérateur unaire attendu
¿Qué estoy haciendo mal?
Respuesta1
Esto es un problema:
if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
Dado que si grep
no encuentra nada, no genera nada, y el lado izquierdo de esto no será nada, lo cual es un error. También es un problema si encuentra algo, ya que la salida podría contener espacios en blanco (por ejemplo, si vm.swappiness
está en el archivo varias veces). Es necesario citarlo o aparecerá como una serie de cadenas distintas cuando se expanda.
Por lo tanto, debe utilizarlo if [ "$(grep ...)" ]
para que se cite el resultado. Si no hay salida, tiene ""
, lo cual está bien en cualquier lado de una prueba en bash.
Sin embargo, en este caso recomendaría usar elestado de salidade grep en su lugar. De man grep
:
ESTADO DE SALIDA
Normalmente, el estado de salida es 0 si se encuentran las líneas seleccionadas y 1 en caso contrario. Pero el estado de salida es 2 si ocurrió un error...
También es útil aquí el -q
interruptor:
-q, --tranquilo, --silencioso
Tranquilo; no escriba nada en la salida estándar. Salir inmediatamentecon estado cerosi se encuentra alguna coincidencia, incluso si se detectó un error.
Entonces, tenga en cuenta $?
el estado de salida del último proceso en primer plano completado:
grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then
Esta condición será verdadera si grep
no se encontró nada y no se produjo ningún error.
Respuesta2
Podría ser porque grep
no devuelves nada. Como no está citado, aparece ese mensaje de error (se espera un operador unario). Intentar:-
if [ "$(grep vm.swappiness /etc/sysctl.conf)" != "vm.swappiness=5" ]; then
Respuesta3
Solo con fines inspiradores, tal vez necesite algunos 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
También podría ser bueno incluir esto en una función, por lo que también puedes llamarlo con el siguiente parámetro.
Respuesta4
Probablemente esto funcione:
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"
Probablemente también deberías salirte sudo
de ese guión. Si es necesario, ejecute el script.con sudo
Me gusta sudo ./script.sh
y manténgalo como un módulo separado de otros scripts. De lo contrario hazlo:
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"
'
Pero no lo recomiendo.