Befehl wird über *.sh Script nicht erkannt.

Zalatschenko

Cadet 2nd Year
Registriert
Dez. 2019
Beiträge
24
Hallo zusammen

Ich möchte auf meinem Raspberry ein Automatisches Update Script Einrichten.
Bash:
#!/bin/bash
#Automatisches Update mit Anschliessendem Reboot
#Beenden aller Docker Container:
sudo docker-compose -f /home/pi/docker-compose.yml down
# Updates Suchen und Laden
sudo apt-get --yes update && sudo apt-get --yes upgrade
# Deinstallation ungenutzter Abhängigkeiten &  Pakete, die nicht mehr in den Quellen verfügbar sind werden gelöscht
sudo apt-get --yes autoremove && sudo apt-get --yes autoclean
#TXT zur Überprüfung erstellen
sudo /home/pi/Loggs/UPDATE_LOG_FULL_UPDATE.txt
# Eintrag in LOG
echo 'Update und Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/Loggs/UPDATE_LOG_FULL_UPDATE.txt
#Pause für 30 sec.
sleep 30
# Raspberry Neustart
sudo reboot
Das Script hab ich anschliessend über sudo chmod +x /xxxx/xxx.sh ausführbar gemacht (zumindest verstand ich das so).
Beim ausführen bekomme ich jedoch den fehler: No such command: down
Bash:
pi@raspberrypi:~ $ sh update_und_neustart.sh
: not foundneustart.sh: 2: update_und_neustart.sh:
No such command: down

Commands:
  build              Build or rebuild services
  bundle             Generate a Docker bundle from the Compose file
  config             Validate and view the Compose file
  create             Create services
  down               Stop and remove containers, networks, images, and volumes
Das witzige ist dass ein paar zeilen darunter der command steht down Stop and remove containers, networks, images, and volumes.

Wenn ich den Befehl sudo docker-compose -f /home/pi/docker-compose.yml down normal über die Console eingebe nimmt er ihn ohne Probleme an.....
Bash:
pi@raspberrypi:~ $ sudo docker-compose -f /home/pi/docker-compose.yml down
WARNING: Some networks were defined but are not used by any service: net
Stopping openhab           ... done
Stopping habridge          ... done
Hatte das Script veruchsweise schon unter /usr/local/bin abgelegt keine änderung.

Jemand eine Idee?

Danke im Voraus.

Gruss
 
Zalatschenko schrieb:
Wenn ich den Befehl sudo docker-compose -f /home/pi/docker-compose.yml down normal über die Console eingebe nimmt er ihn ohne Probleme an.....
Die Frage ist , warum das funktioniert. Denn laut dieser Manpage kennt docker-compose kein command "down".
Was gibt "which docker-compose" aus. Und zwar einmal ins Script eingebaut und zum Vergleich auf der Kommandozeile ?
 
mkossmann schrieb:
Die Frage ist , warum das funktioniert. Denn laut dieser Manpage kennt docker-compose kein command "down".
Was gibt "which docker-compose" aus. Und zwar einmal ins Script eingebaut und zum Vergleich auf der Kommandozeile ?

Nach der Dockumentation von Docker gibt es down: https://docs.docker.com/compose/reference/overview/ oder direkt https://docs.docker.com/compose/reference/down/.
Which Docer-compose:
/usr/local/bin/docker-compose

Bash:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import sys

from compose.cli.main import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())
 
Du willst per Script deinen Host aktualisieren aber nicht die verwendeten Docker Images?^^

Grundlegend soll/muss man sich ja mit der Verwendung von sudo per Kennwort authentifizieren sofern du nicht deine sudoers Datei entsprechend modifiziert hast.
Ich würde da ggf. eher überall das sudo entfernen und das Script mittels sudo script.sh aufrufen oder in die crontab von root packen.

Zum Hauptproblem: Ich würde ggf. darauf tippen, dass der Aufruf innerhalb des Scripts nicht die passenden PATH Variablen hat und daher docker-compose nicht findet. Was passiert wenn du nur ein "docker-compose help" oder "docker-compose version" aufrufst? Bekommst du dann eine saubere Rückmeldung? Falls nicht würde ich den absoluten Pfad zu docker-compose angeben.

Zeile 10 hat auch einen Fehler... Anstatt sudo /path/to/logfile musst schon sagen was da passieren soll. Willst du die Datei anlegen sofern nicht schon vorhanden? Dann wäre sudo touch /path/to/file das sinnvollste. Bonuspunkte wenn du vorher prüfst ob die Datei vorhanden ist.
Ebenso könntest du nach der Installation der Updates überprüfen ob überhaupt ein Reboot notwendig ist. Linux ist kein Windows wo nach jeder Änderung und Update ein Reboot notwendig ist. In der Regel ist das nur notwendig bei Kernelpatches bzw. bei neuen Kerneln ;)
 
  • Gefällt mir
Reaktionen: Zalatschenko
Sry hab momentan ein wenig Zeitprobleme....
Also hab es nun mehrheitlich hinbekommen. (Nur weiss ich nicht wieso xD
Zum Hauptproblem: Ich würde ggf. darauf tippen, dass der Aufruf innerhalb des Scripts nicht die passenden PATH Variablen hat und daher docker-compose nicht findet. Was passiert wenn du nur ein "docker-compose help" oder "docker-compose version" aufrufst? Bekommst du dann eine saubere Rückmeldung? Falls nicht würde ich den absoluten Pfad zu docker-compose angeben.
Hatte ich getestet ohne Erfolg bekam immernoch die Fehlermeldung "down" nicht vorhanden.
Danach wollte ich mich an den 2ten Teil wagen:
Zeile 10 hat auch einen Fehler... Anstatt sudo /path/to/logfile musst schon sagen was da passieren soll. Willst du die Datei anlegen sofern nicht schon vorhanden? Dann wäre sudo touch /path/to/file das sinnvollste. Bonuspunkte wenn du vorher prüfst ob die Datei vorhanden ist.
Ebenso könntest du nach der Installation der Updates überprüfen ob überhaupt ein Reboot notwendig ist. Linux ist kein Windows wo nach jeder Änderung und Update ein Reboot notwendig ist. In der Regel ist das nur notwendig bei Kernelpatches bzw. bei neuen Kerneln
Da ich nicht "wirklich" Programmieren bzw. Coden kann hab ich schon mit diesen Dingen meine Probleme xD
Hab mir aber schlussentlich was zusammengebastelt. Da ich mir Fehlermeldungen auch in den Logg schmeissen wollte hab ich den Befehl docker-compose down ebenfalls eingebaut um zu schauen ob der error export funktioniert.
Und Plötzlich funktioniert docker-compose down......
Keine Ahnung was jetzt der unterschied zum erstenmal ist.
Hier der Code:
Bash:
#!/bin/bash

#LOGG Pfad und Datei erstellen
for path in /home/pi/loggs; do
    if [ -d $path ]; then
        echo 'Pfad loggs ist vorhanden.'
    else
        mkdir /home/pi/loggs
        echo 'Pfad loggs wurde erstellt.'
    fi
done
for file in /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt; do
    if [ -f $file ]; then
        echo 'Logg Datei ist vorhanden.'
    else
        touch /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
        echo 'Logg Datei wurde erstellt.'
    fi
done

# Eintrag "Start" in LOG
echo 'Start Update:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
#Automatisches Update mit Anschliessendem Reboot
#Beenden aller Docker Container:
docker-compose -f /home/pi/docker-compose.yml down
# Eintrag "Ende" in LOG
command 2>> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
echo 'Update inkl. Docker images und Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
Hat jemand eine Idee wieso das plötzlich Funktioniert?

Werde mich jetzt mal an das Update wagen. Mal schauen ob ich es hinbekomme zu überprüfen ob die Updates Kernel-Updates sind oder nicht ...

Danke schonmal für die bisherige Hilfe!

Gruss

PS: Ja das sudo vor den Befehlen hab ich jetzt weggelassen. Jedoch hat das beim alten Script nichts geändert die Fehlermeldung kam immernoch.
Beide Scripts hab ich mit chmod -x xxxx.sh vorbereitet.
Und ja hab gerade auch bemerkt dass der Logg überschrieben und nicht erweitert wird 🙈 - - > ist angepasst
 
Zuletzt bearbeitet:
Also: Bin nun recht zufrieden. Habe mir debian-goodies Installiert damit ich über
checkrestart eine INFO erhalte ob Packete einen Neustart benötigen oder nicht.
Danach wird über if entschieden ob der Neustart ausgeführt wird.
Die ganzen Docker Befehle Funktionieren jetzt auch einwandfrei. Sollten Fehler entstehen werden diese ausgelesen und ins Logg File geschrieben.
Wieso der Fehler auftrat kann ich leider nicht sagen. Habe an den Grundeinstellungen ja nichts geändert.

Hier wäre jetzt mein Code:

Bash:
#!/bin/bash

#LOGG Pfad und Datei erstellen
for path1 in /home/pi/loggs; do
    if [ -d $path1 ]; then
        echo 'Pfad loggs ist vorhanden.'
    else
        mkdir /home/pi/loggs
        echo 'Pfad loggs wurde erstellt.'
    fi
done
for file1 in /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt; do
    if [ -f $file1 ]; then
        echo 'Logg Datei ist vorhanden.'
    else
        touch /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
        echo 'Logg Datei wurde erstellt.'
    fi
done

# Eintrag "Start" in LOG
echo 'Start Update:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt

#Automatisches Update mit Anschliessendem Reboot
#Beenden aller Docker Container:
docker-compose -f /home/pi/docker-compose.yml down 1>> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt

# Updates Suchen und Laden
apt-get -y update && sudo apt-get -y upgrade 2>> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt

#Updates von Docker suchen und Laden
#docker images | grep -v REPOSITORY | awk '{print $1}' | xargs -L1 docker pull

# Deinstallation ungenutzter Abhängigkeiten &  Pakete, die nicht mehr in den Quellen verfügbar sind werden gelöscht
# apt-get autoremove && sudo apt-get autoclean 2> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt

# Check
#TXT bereitstellen
for file2 in /home/pi/loggs/checkupdate.txt; do
    if [ -f $file2 ]; then
        echo 'Logg Datei ist vorhanden.'
    else
        touch /home/pi/loggs/checkupdate.txt
        echo 'Logg Datei wurde erstellt.'
    fi
done

#Prüfen ob Update Notwendig und falls Ja weiter mit Neustart ansonsten alle Docker Container neu Starten.
checkrestart > /home/pi/loggs/checkupdate.txt
if grep -i -q 'No packages seem to need to be restarted\|Found 0 processes using old versions of upgraded files' /home/pi/loggs/checkupdate.txt; then
    echo 'Es wird kein Neustart benötigt' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
    echo 'Update ohne Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
    docker-compose -f /home/pi/docker-compose.yml up -d 1>> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
else
    echo 'Es wird ein Neustart benötigt! Neustart 30 Sekunden nach Abschluss.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
    echo 'Update und Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> /home/pi/loggs/UPDATE_LOG_FULL_UPDATE.txt
    sleep 30
    reboot
fi

Falls jemand mal Zeit hat würde ich mich über Rückmeldungen zu dem oberhalb eingefügten Code Freuen :))

Gruss
 
OK, ein paar Rückmeldungen (du wolltest es so... 😉 ):
  1. Nutze keine for-Schleifen, wo sie nicht nötig sind. Das verwirrt nur.
  2. Nimm für deine Pfade und Dateien wo immer es geht Variablen, das erleichtert später Änderungen und die Fehlersuche.
  3. Wenn du in Dateien schreibst (mit > oder >>), dann musst du diese in der Regel nicht vorher anlegen.
  4. Ganz wichtig: Wenn das Skript im Shebang (1. Zeile) "bash" möchte, dann solltest du es an der Shell nicht mit "sh name.sh" aufrufen, wie in deinem ersten Post hier. Du hattest es ja mit "chmod +x" bereits ausführbar gemacht, deswegen musst du den Interpreter nicht mehr angeben, sondern kannst es direkt starten. Oder aber mit der richtigen Shell "bash name.sh". Für die Fehlersuche kann auch "bash -x name.sh" sehr erleuchtend sein.
Ich habe es mal ein wenig angepasst:
Bash:
#!/bin/bash

#LOGG Pfad und Datei erstellen
log_path=/home/pi/loggs
log_file=$log_path/UPDATE_LOG_FULL_UPDATE.txt

if [ -d $log_path ]; then
    echo 'Pfad loggs ist vorhanden.'
else
    mkdir -p $log_path
    echo 'Pfad loggs wurde erstellt.'
fi

# Eintrag "Start" in LOG
echo 'Start Update:' $(date +%Y%m%d_%H%M%S%Z)'.' >> $log_file

#Automatisches Update mit Anschliessendem Reboot
#Beenden aller Docker Container:
docker-compose -f /home/pi/docker-compose.yml down 1>> $log_file

# Updates Suchen und Laden
apt-get -y update && apt-get -y upgrade 2>> $log_file

#Updates von Docker suchen und Laden
#docker images | grep -v REPOSITORY | awk '{print $1}' | xargs -L1 docker pull

# Deinstallation ungenutzter Abhängigkeiten &  Pakete, die nicht mehr in den Quellen verfügbar sind werden gelöscht
# apt-get autoremove && apt-get autoclean 2>> $log_file

# Check
chk_file=$log_path/checkupdate.txt

#Prüfen ob Update Notwendig und falls Ja weiter mit Neustart ansonsten alle Docker Container neu Starten.
checkrestart > $chk_file
if grep -i -q 'No packages seem to need to be restarted\|Found 0 processes using old versions of upgraded files' $chk_file; then
    echo 'Es wird kein Neustart benötigt' >> $log_file
    echo 'Update ohne Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> $log_file
    docker-compose -f /home/pi/docker-compose.yml up -d 1>> $log_file
else
    echo 'Es wird ein Neustart benötigt! Neustart 30 Sekunden nach Abschluss.' >> $log_file
    echo 'Update und Reboot durchgeführt am:' $(date +%Y%m%d_%H%M%S%Z)'.' >> $log_file
    sleep 30
    reboot
fi
 
  • Gefällt mir
Reaktionen: Zalatschenko
Danke für die Rückmeldung. Als änfänger sind solche Tipps Gold wert ^^

??? schrieb:
  1. Ganz wichtig: Wenn das Skript im Shebang (1. Zeile) "bash" möchte, dann solltest du es an der Shell nicht mit "sh name.sh" aufrufen, wie in deinem ersten Post hier. Du hattest es ja mit "chmod +x" bereits ausführbar gemacht, deswegen musst du den Interpreter nicht mehr angeben, sondern kannst es direkt starten. Oder aber mit der richtigen Shell "bash name.sh". Für die Fehlersuche kann auch "bash -x name.sh" sehr erleuchtend sein.
[/CODE]
Das muss ich mir noch anschauen für mich ist sh und bash bei der ausführung das selbe 😅
Gruss
 
Zalatschenko schrieb:
für mich ist sh und bash bei der ausführung das selbe 😅
Das kann manchmal stimmen (z.B. bei arch), aber oft wird sh auch auf dash gelinkt (z.B. bei Debian) und das ist durchaus etwas anderes als bash.
 
Zalatschenko schrieb:
Für mich ist sh und bash bei der ausführung das selbe 😅
Die bash ändert ihr Verhalten, wenn sie als sh aufgerufen wird. Die man page sagt dazu:
If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well
 
Zurück
Oben