Ich möchte ein Skript erstellen, um einige benutzerdefinierte Konfigurationen automatisch auf textbasierte Konfigurationsdateien anzuwenden.
Im vorliegenden Fall versuche ich, zwei Zeilen hinzuzufügen, /etc/sysctl.conf
falls diese Zeilen noch nicht in der Datei vorhanden sind (um ein mehrfaches Vorkommen dieser Zeilen in der Datei zu vermeiden).
hier ist das Skript, das ich verwende:
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
und der Fehler, den ich bekomme:
/home/erwan/Workspace/Install.sh: ligne 19 : [: != : opérateur unaire attendu
/home/erwan/Workspace/Install.sh: ligne 23 : [: != : opérateur unaire attendu
Was mache ich falsch?
Antwort1
Das ist ein Problem:
if [ `grep vm.swappiness /etc/sysctl.conf` != "vm.swappiness=5" ]; then
Da „if grep
“ nichts findet, wird auch nichts ausgegeben und die linke Seite enthält nichts, was ein Fehler ist. Es ist auch ein Problem, wenn etwas gefunden wird, da die Ausgabe Leerzeichen enthalten könnte (z. B. wenn „if“ vm.swappiness
mehrfach in der Datei vorkommt). Diese müssen in Anführungszeichen gesetzt werden, sonst wird es beim Erweitern als eine Reihe unterschiedlicher Zeichenfolgen angezeigt.
Sie sollten daher verwenden, if [ "$(grep ...)" ]
damit die Ausgabe in Anführungszeichen steht. Wenn keine Ausgabe erfolgt, haben Sie ""
, was auf beiden Seiten eines Tests in Bash in Ordnung ist.
In diesem Fall empfehle ich jedoch die Verwendung vonBeendigungsstatusvon grep stattdessen. Von man grep
:
Beendigungsstatus
Normalerweise ist der Beendigungsstatus 0, wenn die ausgewählten Zeilen gefunden wurden, und andernfalls 1. Der Beendigungsstatus ist jedoch 2, wenn ein Fehler aufgetreten ist ...
Auch nützlich ist hier der -q
Schalter:
-q, --quiet, --silent
Leise; schreibt nichts in die Standardausgabe. Beendet sofortmit Nullstatuswenn eine Übereinstimmung gefunden wird, auch wenn ein Fehler erkannt wurde.
Beachten Sie daher $?
den Beendigungsstatus des letzten abgeschlossenen Vordergrundprozesses:
grep -q grep vm.vfs_cache_pressure /etc/sysctl.conf
if [ $? -eq 1 ]; then
Diese Bedingung ist erfüllt, wenn grep
nichts gefunden wurde und kein Fehler aufgetreten ist.
Antwort2
Es könnte daran liegen, dass Ihr grep
nichts zurückgibt. Da es nicht zitiert ist, erhalten Sie diese Fehlermeldung (unärer Operator erwartet). Versuchen Sie:-
if [ "$(grep vm.swappiness /etc/sysctl.conf)" != "vm.swappiness=5" ]; then
Antwort3
Nur zur Inspiration, muss vielleicht noch etwas optimiert werden:
#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
Es könnte auch sinnvoll sein, dies in eine Funktion einzubinden, sodass Sie diese auch mit Ihrem nächsten Parameter aufrufen können.
Antwort4
Das würde wahrscheinlich funktionieren:
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"
Sie sollten sudo
dieses Skript wahrscheinlich auch beenden. Führen Sie bei Bedarf das Skript ausmit sudo
sudo ./script.sh
und behalte es als separates Modul von anderen Skripten. Andernfalls mache :
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"
'
Aber ich empfehle es nicht.