ubuntuusers.de

Shell Skript Bad substitution

Status: Gelöst | Ubuntu-Version: Ubuntu 19.10 (Eoan Ermine)
Antworten |

m.g.o.d

Anmeldungsdatum:
18. November 2019

Beiträge: 29

Hallo liebe Ubuntu Community,

ich habe ein Shell Skript geschrieben, was ich gestestet habe. Zeile für Zeile und auch den Inhalt der Variablen. Alles war ok. Während der Testphase habe ich dieses Skript unter meinem User getestet. Nach Fertigstellung sollte es als Cronjob und vom user Root (wahrscheinlich das Problem) jede 2 Minuten aufgerufen werden. Ich bekam ein Log via Pipe in mein Homeverzeichnis mit Fehlermeldungen, die ich nicht kapiere. Und zwar deshalb, weil vorher alles funktioniert hat. Jetzt plötzlich nicht mehr?! Ich habe jedes Zeichen ganz genau überprüft. Alles müsste stimmen, die Ergebnisse zuvor waren ja auch in Ordnung...ich bin verwirrt.

Kurz zur Erklärung was das Skript machen soll: Wenn auf dem Server ein Videostream abstürzt: Output Status 0, dann soll mein Skript greifen und ein paar damit in Zusammenhängende Skripts starten, die dann ein Neustart sowie die Erzeugung von einigen Logfiles veranlasst. Die Logik ist einfach, wenn der Outputstatus ungleich 1 ist (abgefragt über SNMP) dann löse die ganzen Skripte aus.

Hier wäre der Quellcode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash

uuids=( $(find /opt/playout/etc/output-*.json | grep -Po '(?<=-).*(?=.log)') )                              # UUIDS sind eindeutige IDs der auf dem Server laufenden Channel
date=`date +%Y-%m-%d-%H-%M`

for uuid in ${uuids[@]};

do

    oids_tableindex=$(cat /opt/playout/etc/playout-${uuid}.json | grep 'snmp' | grep -Po '(?<=: ).*(?=,)')  # OIDs für die SNMP Abfrage 
    outputstatus=$(snmpget -v 2c -c public localhost iso.3.6.1.4.1.44502.0.0.1.1.2.$oids_tableindex)        # Outputstatus je OID --> 1:Ok, 0:schlecht
    outputstatusgood="iso.3.6.1.4.1.44502.0.0.1.1.2.$oids_tableindex = INTEGER: 1"                          # Status zur Apprüfung: 1:Ok


    if [ "$outputstatus" != "$outputstatusgood" ]
    then
        yes | /opt/playout/playout-$uuid.sh restart syncer input capture controller output > /dev/null      # Ausführung eines restart-Skripts mit Übergabe Y
        /opt/playout/playout-report-incident-$uuid.sh                                                       # Ausführung eines Report creating Skripts                                              
        mv /root/playout_report_incident_$uuid"_"*.gz /var/log/autoprestart/                                # Verschieben des Logs in richtiges VZ
        dmesg -t >> /var/log/autoprestart/$uuid"_"$date"_"kernel.log                                        # Erstellung eines Kernellogs inkl. $Date
        echo "restart was done at:" $date >> /var/log/autoprestart/$uuid"_"neustart.log                     # Erstellung eines Neustart Logs (wie oft?)
        sleep 1m                                                                                            # Zeit damit die SNMP Abfrage wieder aktualiert werden kann

    fi

find /root/var/log/autoprestart -iname "*.var.gz" -ctime +10 -delete > /dev/null                            # Löschung der Logs die älter als 10 Tage sind
find /root/var/log/autoprestart -iname "*.kernel.log" -ctime +10 -delete > /dev/null
find /root/var/log/autoprestart -iname "*.neustart.log" -ctime +30 -delete > /dev/null

done;

Wie gesagt, wenn ich dieses Skript mit meinem User ausführe, klappt alles wie es soll. Nun hier das Log, welches vom root User kommt:

Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.
Error: no such file "86d3af84-cdcd-4d8a-9f02-714e5d28fae1"
Error: no such file "a91dbef5-7a3f-4509-ae43-83338260d184"
/home/godhoff/autoprestart.sh: 9: /home/godhoff/autoprestart.sh: Bad substitutio n
find: ‘/opt/playout/etc/output-*.json’: No such file or directory
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.
/home/godhoff/autoprestart.sh: 9: /home/godhoff/autoprestart.sh: Bad substitutio n
/home/godhoff/autoprestart.sh: 4: /home/godhoff/autoprestart.sh: Syntax error: " (" unexpected

Nchts davon macht für mich Sinn. Der erste Fehler bezieht sich wohl auf diese Zeile: oids_tableindex=$(cat /opt/playout/etc/playout-${uuid}.json | grep 'snmp' | grep -Po '(?⇐: ).*(?=,)')

Die Ausgabe der Variable oids_tableindex ergibt sinnvolle Werte.

Line 528 gibt es in meinem Shell Skript nicht. Keine Ahnung was das bedeuten soll.

Und mit der Bad substitution Meldung kann ich leider auch nix anfangen, weil die Syntax nach dem Test (inklusive Debug Modus set -x) für jede Zeile gestimmt hat.

Hat jemand von euch einen Rat? Bei Unklarheiten helfe ich gerne, wo ich kann. Aber ich bin sicher kein Shell crack ☺

Viele Grüße, Marc

Bearbeitet von rklm:

Codeblock. Bitte nutze Codeblöcke und die Vorschaufunktion!

dingsbums

Anmeldungsdatum:
13. November 2010

Beiträge: 3790

Prüfe mal, ob bei root die gleiche Shell eingestellt ist wie bei deinem Benutzerkonto. Also einmal als godhoff:

printenv | grep -i shell

Dann interaktiv als root anmelden und das Gleiche nochmal:

sudo -i
printenv | grep -i shell

Standardmäßig müsste meines Wissens bei beiden Folgendes herauskommen:

SHELL=/bin/bash

m.g.o.d

(Themenstarter)

Anmeldungsdatum:
18. November 2019

Beiträge: 29

dingsbums schrieb:

Prüfe mal, ob bei root die gleiche Shell eingestellt ist wie bei deinem Benutzerkonto. Also einmal als godhoff:

printenv | grep -i shell

Dann interaktiv als root anmelden und das Gleiche nochmal:

sudo -i
printenv | grep -i shell

Standardmäßig müsste meines Wissens bei beiden Folgendes herauskommen:

SHELL=/bin/bash

Hi, danke für deinen Hinweiß. Ich frage nach (bin leider nicht der root) und melde mich mit der Information!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13205

m.g.o.d schrieb:

Wie gesagt, wenn ich dieses Skript mit meinem User ausführe, klappt alles wie es soll. Nun hier das Log, welches vom root User kommt:

Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.
Error: no such file "86d3af84-cdcd-4d8a-9f02-714e5d28fae1"
Error: no such file "a91dbef5-7a3f-4509-ae43-83338260d184"
/home/godhoff/autoprestart.sh: 9: /home/godhoff/autoprestart.sh: Bad substitutio n
find: ‘/opt/playout/etc/output-*.json’: No such file or directory
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.
/home/godhoff/autoprestart.sh: 9: /home/godhoff/autoprestart.sh: Bad substitutio n
/home/godhoff/autoprestart.sh: 4: /home/godhoff/autoprestart.sh: Syntax error: " (" unexpected

In dem Skript taucht kein Aufruf von print auf, der hier angemeckert wird. Also muss das irgendwo anders sitzen. Wir müssen das mal debuggen. Kannst Du mal das Skript so ausführen und die Ausgabe im Codeblock posten:

1
sudo /bin/bash -x script/pfad argumente

Insgesamt habe ich den Eindruck, dass es Quoting-Probleme gibt. Ich weiß z.B. nicht, was in der Variable oids_tableindex landet. Falls da Leerzeichen sind, sollte es in Zeile 11 so aussehen:

1
outputstatus=$(snmpget -v 2c -c public localhost "iso.3.6.1.4.1.44502.0.0.1.1.2.$oids_tableindex")

m.g.o.d

(Themenstarter)

Anmeldungsdatum:
18. November 2019

Beiträge: 29

Hi, sehr gerne:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

+ uuids=($(find /opt/playout/etc/output-*.json | grep -Po '(?<=-).*(?=.log)'))

++ find /opt/playout/etc/output-86d3af84-cdcd-4d8a-9f02-714e5d28fae1.log.json /opt/playout/etc/output-a91dbef5-7a3f-4509-ae43-83338260d184.log.json

++ grep -Po '(?<=-).*(?=.log)'

+ print 86d3af84-cdcd-4d8a-9f02-714e5d28fae1

Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.

Error: no such file "86d3af84-cdcd-4d8a-9f02-714e5d28fae1"

++ date +%Y-%m-%d-%H-%M

+ date=2020-03-10-18-07

+ for uuid in '${uuids[@]}'

++ cat /opt/playout/etc/playout-86d3af84-cdcd-4d8a-9f02-714e5d28fae1.json

++ grep snmp

++ grep -Po '(?<=: ).*(?=,)'

+ oids_tableindex=9

++ snmpget -v 2c -c public localhost iso.3.6.1.4.1.44502.0.0.1.1.2.9

+ outputstatus='iso.3.6.1.4.1.44502.0.0.1.1.2.9 = INTEGER: 1'

+ outputstatusgood='iso.3.6.1.4.1.44502.0.0.1.1.2.9 = INTEGER: 1'

+ '[' 'iso.3.6.1.4.1.44502.0.0.1.1.2.9 = INTEGER: 1' '!=' 'iso.3.6.1.4.1.44502.0.0.1.1.2.9 = INTEGER: 1' ']'

+ for uuid in '${uuids[@]}'

++ cat /opt/playout/etc/playout-a91dbef5-7a3f-4509-ae43-83338260d184.json

++ grep -Po '(?<=: ).*(?=,)'

++ grep snmp

+ oids_tableindex=5

++ snmpget -v 2c -c public localhost iso.3.6.1.4.1.44502.0.0.1.1.2.5

+ outputstatus='iso.3.6.1.4.1.44502.0.0.1.1.2.5 = INTEGER: 1'

+ outputstatusgood='iso.3.6.1.4.1.44502.0.0.1.1.2.5 = INTEGER: 1'

+ '[' 'iso.3.6.1.4.1.44502.0.0.1.1.2.5 = INTEGER: 1' '!=' 'iso.3.6.1.4.1.44502.0.0.1.1.2.5 = INTEGER: 1' ']'

Warum hier die Zeile :

1
2
3
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at /usr/bin/print line 528.

Error: no such file "86d3af84-cdcd-4d8a-9f02-714e5d28fae1"

auftaucht, ist neu. Ich hatte das vorher nicht.

In der oid_tableindex landet nur eine Zahl ohne Leerzeiche:

1
++ snmpget -v 2c -c public localhost iso.3.6.1.4.1.44502.0.0.1.1.2.9

die Zahl 9 ist die oid_tableindex in dem Fall. Im nächsten Schleifendurchlauf wird der Wert 5 ermittelt (Da andere UUID abgefragt wird). Wäre dort ein Leerzeichen falsch enthalten, würde die Anfrage via SNMP nicht funktionieren. Das hatte ich beim Erstellen des Skripts und dann beseitigt.

1
2

grep -Po '(?<=-).*(?=.log)'))

Dieser Ausdruck extrahiert genau diese eine Ziffer. Das funktioniert ja auch im nachfolgenden Verlauf des Skripts prima.

1
Error: no such file "86d3af84-cdcd-4d8a-9f02-714e5d28fae1"

Hier handelt es sich nur um einen String (warum meint die Shell eine Datei?!), den ich lediglich in die Variable uuids speichere und danach auch fehlerfrei weiter verwende. Diese Fehlermeldung ist nicht nachvollziehbar für mich.

m.g.o.d

(Themenstarter)

Anmeldungsdatum:
18. November 2019

Beiträge: 29

Also die merkwürdige Situation ist folgende: Das Skript funktioniert. Bringt aber die Fehlermeldungen, die irgendwie beseitigt werden müssen und ich weiss nicht was die bedeuten sollen... 😳

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13205

m.g.o.d schrieb:

Hi, sehr gerne:

Bitte poste mal die originale Ausgabe. Da sind mindestens Leerzeilen zu viel. Bearbeitest Du hier vielleicht was mit einem Windows-Editor?

m.g.o.d

(Themenstarter)

Anmeldungsdatum:
18. November 2019

Beiträge: 29

rklm schrieb:

m.g.o.d schrieb:

Hi, sehr gerne:

Bitte poste mal die originale Ausgabe. Da sind mindestens Leerzeilen zu viel. Bearbeitest Du hier vielleicht was mit einem Windows-Editor?

Puh, das kann sein. Ich schreibe das Skript mit dem vi(m) Editor und kopiere den Text in eine Textdatei.txt, die ich wiederrum in einem Dokutool (Confluence) zwischenspeichere. Und von dort kommt der Text hier rein. Anders kann ich es technisch nicht machen. Aber würde eine Leerzeile in Zusammenhang mit der Fehlermeldung stehen? Er meckert ja eigenlich Bad substitution an und das es einen String als Datei nicht gäbe...was Unsinn ist.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13205

m.g.o.d schrieb:

rklm schrieb:

Bitte poste mal die originale Ausgabe. Da sind mindestens Leerzeilen zu viel. Bearbeitest Du hier vielleicht was mit einem Windows-Editor?

Puh, das kann sein. Ich schreibe das Skript mit dem vi(m) Editor und kopiere den Text in eine Textdatei.txt, die ich wiederrum in einem Dokutool (Confluence) zwischenspeichere. Und von dort kommt der Text hier rein. Anders kann ich es technisch nicht machen. Aber würde eine Leerzeile in Zusammenhang mit der Fehlermeldung stehen?

Mindestens macht es die Ausgabe schwerer lesbar, und oft genug gab es hier Probleme, die sich nachträglich als Effekt von Windows-Zeilenenden herausgestellt hat. Deine Bearbeitungs-Pipeline ist ziemlich unsicher. Wir müssen schon genau das sehen, was auf der Maschine passiert ist. Warum Du in Confluence zwischenspeichern musst, um hier zu posten ist mir total schleierhaft. Man kann jedenfalls ein Problem nicht analysieren, wenn man nicht die Fakten kennt - das sind in diesem Fall das originale Skript und die originale Ausgabe.

m.g.o.d

(Themenstarter)

Anmeldungsdatum:
18. November 2019

Beiträge: 29

Hallo Zusammen, tatsächlich ist das Problem, das bei root die SH Shell und nicht die bash als ausführende Shell eingestellt ist. Ich habe schon gesehen das mein Skript mit

1
#!/bin/bash

problemlos funktioniert. Wird hingegen

1
#!/bin/sh

angegeben, kommen Syntaxfehler ☹

Jetzt muss ich auf die andere Shell anpassen oder die ausführende Shell vom Root muss auf Bash geändert werden. Jedenfalls liegt hier der Fehler. Danke für eure Hinweiße!!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13205

m.g.o.d schrieb:

Hallo Zusammen, tatsächlich ist das Problem, das bei root die SH Shell und nicht die bash als ausführende Shell eingestellt ist.

Die Shell des Nutzers ist für ein Script mit Shebang-Zeile völlig irrelevant.

Ich habe schon gesehen das mein Skript mit

1
#!/bin/bash

problemlos funktioniert. Wird hingegen

1
#!/bin/sh

angegeben, kommen Syntaxfehler ☹

Jetzt muss ich auf die andere Shell anpassen oder die ausführende Shell vom Root muss auf Bash geändert werden. Jedenfalls liegt hier der Fehler. Danke für eure Hinweiße!!

Die Shebang-Zeile in Deinem ersten Posting zeigt /bin/bash. Dann verstehe ich nicht, warum Du überhaupt ein Problem hast. Das ist genau das, was ich vorher meinte: wir müssen schon die Fakten kennen, sonst können wir nicht wirklich helfen. Für jeden, der hier helfen will, ist es ungemein frustrierend nach einem Fehler zu suchen und plötzlich festzustellen, dass man von falschen Voraussetzungen ausgegangen ist. Bitte poste in Zukunft ein konsistentes Bild, also Fehlermeldungen und die zugehörigen Skripte, die es ausgelöst haben - ohne nachträgliche Änderungen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

rklm schrieb:

Das ist genau das, was ich vorher meinte: wir müssen schon die Fakten kennen, sonst können wir nicht wirklich helfen.

Das stimmt zwar, aber Fehlersuche ist ein iterativer Prozess. Was die relevanten Fakten sind, weiß man, wenn man das Problem gelöst hat (meistens).

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13205

user_unknown schrieb:

rklm schrieb:

Das ist genau das, was ich vorher meinte: wir müssen schon die Fakten kennen, sonst können wir nicht wirklich helfen.

Das stimmt zwar, aber Fehlersuche ist ein iterativer Prozess. Was die relevanten Fakten sind, weiß man, wenn man das Problem gelöst hat (meistens).

Klar. Es geht aber darum, dass präsentierte Fehlermeldungen und der Code, der ihn produziert hat, konsistent sind. Es ergibt wenig Sinn, einen Fehler finden zu wollen, wenn das Programm, das man sieht, ein anderes (geändertes) ist.

Antworten |