"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

bash script hilfe benötigt

Indigo 18.06.2020 - 10:52 3016 12
Posts

Indigo

raub_UrhG_vergewaltiger
Avatar
Registered: Mar 2001
Location: gigritzpotschn
Posts: 6691
habe meinen 3D drucker mittels ESP8266 transparent wifi serial bridge angebunden und möchte, sobald der esp online ist das pseudotty interface am server dazu erzeugen damit ich den drucker per octoprint ansprechen kann

bis jetzt hab ich das tty immer per hand erzeugt

hab mir jetzt folgendes bash script geschrieben, aber es funzt noch nicht so wie ich mir das vorstelle

Code:
#!/bin/bash
x=`/bin/ping -c1 10.0.0.111 2>%1 |grep Unreachable`
file="/dev/ttyESP"

if [ ! "$x" = "" ];
	then
		echo disconnecting && pkill -f "socat pty,rawer,link=/dev/ttyESP,user=octoprint,group=dialout tcp:10.0.0.111:8888" && rm /dev/ttyESP -R

elif [[ "$x" = "" && -f "$file" ]];
	then
		echo already running

elif [[ "$x" = "" && ! -f "$file" ]];
	then
		echo connecting && socat pty,rawer,link=/dev/ttyESP,user=octoprint,group=dialout tcp:10.0.0.111:8888 &
fi

würde das dann per cron jede minute laufen lassen

es soll folgendes erledigen:

wenn esp per ping abwesend: socat prozess killen und ttyESP löschen
wenn esp per ping anwesend und ttyESP nicht vorhanden socat ausführen
wenn esp per ping anwesend und ttyESP vorhanden socat nicht ausführen und script beenden

danke schonmal für die hilfe, ich komm hier mit meinen begrenzten skills nimmer weiter...

davebastard

Vinyl-Sammler
Avatar
Registered: Jun 2002
Location: wean
Posts: 12296
was funzt nicht ? was ist die fehlermeldung ?

COLOSSUS

Administrator
GNUltra
Avatar
Registered: Dec 2000
Location: ~
Posts: 12083
Ohne dein lokales Environment in der Hand zu haben, ist es immer schwer, sowas gesundzuflicken - weil man ja nicht ueber Hypothesen, was genau schieflaeuft, iterieren kann.

Kannst du mal herzeigen, was das Script momentan (nicht) tut via cron? (Bonuspunkte fuer einen Durchlauft mit '#!/bin/bash -x' im Shebang.)

Auf welcher Distro laeuft das? Hast du dort systemd?

Indigo

raub_UrhG_vergewaltiger
Avatar
Registered: Mar 2001
Location: gigritzpotschn
Posts: 6691
aso, ja hätte ich noch gneuaer beschreiben sollen :p

es tut bereits folgendes erfolgreich:
- das tty erzeugen wenn noch nicht vorhanden und per ping erreichbar
- das tty löschen wenn nicht erreichbar

aber die abfrage die feststellen soll ob das tty bereits erstellt ist und erreichbar ist funktioniert nicht, da hupft er immer ins letzte elif rein und versucht es nochmal zu erstellen...

laufen tut das ganze unter debian 10 (systemd vorhanden) in einer hyper-v vm

via cron hab ichs noch garnicht eingebunden, da es ja noch nicht funktioniert...

COLOSSUS

Administrator
GNUltra
Avatar
Registered: Dec 2000
Location: ~
Posts: 12083
Zwei Sachen:

1.) "-f" ist der falsche Test fuer ein TTY-File in /dev/:

Code:
 $ help test | grep -- -f
      -f FILE        True if file exists and is a **regular file.**
(Emph. mine)

TTYs sind "character devices", darauf testet man mit "-c" (wobei in deinem Fall wohl Existenz - "-e" - ausreicht.)


2.) Ich glaube nicht, dass `socat` selbst dieses chardev anlegen kann, wenn du es mal vernichtet/geloescht hast. Das ist eigentlich die Aufgabe des Kernels bzw. von udev, und die Metadaten (type, major, minor) sind wichtiger als der Name der Datei selbst. Schau dir mal mit `stat` an, was fuer den funktionierenden TTY-Devnode zurueck kommt. Fuer meinen ersten Serial TTY hier krieg ich bspw. das:

Code:
$ stat /dev/ttyS0
  File: /dev/ttyS0
  Size: 0               Blocks: 0          IO Block: 4096   character special file
Device: 6h/6d   Inode: 1127        Links: 1     Device type: 4,40
Access: (0660/crw-rw----)  Uid: (    0/    root)   Gid: (   20/ dialout)
Access: 2020-06-13 20:30:05.979999929 +0200
Modify: 2020-06-13 20:30:05.979999929 +0200
Change: 2020-06-13 20:30:05.979999929 +0200
 Birth: -

Du wirst den Devnode, wenn du ihn wirklich loeschen willst (was ist die Motivation dazu?), wieder genau so (in meinem Fall: character device mit major number 4, minor number 40 - mknod(1) hat mehr Info) anlegen muessen, wie er davor war, sonst wird das nix werden koennen.

Indigo

raub_UrhG_vergewaltiger
Avatar
Registered: Mar 2001
Location: gigritzpotschn
Posts: 6691
danke! die änderung von -f auf -e did the trick, jetzt funktioniert es wie gewünscht :thumbsup:

COLOSSUS

Administrator
GNUltra
Avatar
Registered: Dec 2000
Location: ~
Posts: 12083
Schoen, dass es jetzt funktioniert.

Willst Du dein Script in Sachen Stil auch kritisiert haben, oder ist dir das egal? ;)

Indigo

raub_UrhG_vergewaltiger
Avatar
Registered: Mar 2001
Location: gigritzpotschn
Posts: 6691
spars dir, bin eher der funktionelle typ :D

geht, passt :D

Neo-=IuE=-

Here to stay
Registered: Jun 2002
Location: Berndorf, NÖ
Posts: 3232
Also ich würde die Kritik trotzdem gern lesen, weil ich durch sowas auch immer lern ;-)

bsox

Schwarze Socke
Avatar
Registered: Jun 2009
Location: Dschibuti
Posts: 1078
+1
Mich interessieren die Anmerkungen vom Prof. Colossus auch. :)

COLOSSUS

Administrator
GNUltra
Avatar
Registered: Dec 2000
Location: ~
Posts: 12083
Also, das Script hat aus meiner Sicht mehrere Probleme auf unterschiedlichen Ebenen.

Echt falsch ist z. B. die stderr-Redirection in dem Call zu ping - der Benutzer dieses Scripts wird eine Datei Namens "%1" im CWD liegen haben. Gemeint ist wohl "2>&1", um stderr auf stdout zu kriegen. (Dieser etwas subtile Bug fuehrt auch dazu, dass das Script wohl immer noch nicht in allen denkbaren Faellen das macht, was der Autor wirklich von ihm haben moechte!)


Ein Stil-Problem, das aber zu einem echten werden kann, ist folgendes: `somecmd` (backticks) statt $(somecmd) zur command substitution zu verwenden ist generell eine schlechte Idee. $() ist besser lesbar, das Konstrukt laesst sich beliebig verschachteln, und Editoren tun sich leichter mit dem Hervorheben der Syntax. Es gibt KEINEN Grund, jemals irgendwo auf das aeltere `` zurueckzugreifen. In ungefaehr 101 von 100 Faellen ist es auszerdem Notwendig, das Expansionskonstrukt in double quotes zu packen, da man sonst von word splitting aufgeblattelt wird. Zusammengefasst als Handlungsempfehlung:
NIEMALS `somecmd`.
QUASI NIEMALS $(somecmd).
QUASI IMMER "$(somecmd)".


Weiters: Konstrukte wie x="$(some command | grep some-string)" sind in den meisten Faellen irgendwo zwischen unnoetig und falsch. In diesem Fall hier geht es nur darum, sicherzustellen, dass "Unreachable" nicht im Output von `ping` vorkommt, was eine nicht ideale Methode ist, ping zu fragen, ob es erfolgreich hat arbeiten koennen. Das wird von allen gesunden Tools durch den exit status besser und eindeutig beantwortet.

Nachdem ein if-block durch eine if-list nach dem if eroeffnet wird, die von der Shell ausgefuehrt wird ([ und [[ sind Programme bzw. built-ins, die einen exit status zurueckgeben, der von if ausgewertet wird!), koennte man das so eleganter loesen:

Code:
if ping -c1 -w1 10.0.0.111 &>/dev/null
then
 # code wenn Ziel erreichbar
else
 # code wenn Ziel nicht erreichbar
fi

Wenn man mit einer Situation konfrontiert ist, wo der exit status nicht autoritativ aussagekraeftig ist, und man wirklich von grep gesagt bekommen moechte, dass irgendeine regex in seinem Input vorkommt, verwendet man idealerweise grep -q ..., anstatt den Output in eine Shell-Variable zu packen. Das bringt grep dazu, durch seinen eigenen exit status zu sagen, ob der Ausdruck gefunden wurde (und zwar schon nach dem allerersten Match).



Weiters: Oft ist man, wie auch in diesem Fall, damit konfrontiert, mit der Shell einen "entfernten" (=nicht-Kind/Job-)Prozess zu beeinflussen. Das war in pre-systemd-Zeiten muehsam, aber seit systemd-run es einem erlaubt, transient units zu starten (und zu stoppen), ist das viel sauberer moeglich. Als Beispiel:

Code:
colo@ryzealot[ssh:A]:~ $ systemd-run --user --unit myunit /bin/sleep 3600
Running as unit: myunit.service

colo@ryzealot[ssh:A]:~ $ systemctl status --user myunit
● myunit.service - /bin/sleep 3600
     Loaded: loaded (/run/user/1000/systemd/transient/myunit.service; transient)
  Transient: yes
     Active: active (running) since Sun 2020-06-21 19:24:07 CEST; 26s ago
   Main PID: 14666 (sleep)
     CGroup: /user.slice/user-1000.slice/user@1000.service/myunit.service
             └─14666 /bin/sleep 3600


Jun 21 19:24:07 ryzealot systemd[622]: Started /bin/sleep 3600.
colo@ryzealot[ssh:A]:~ $ systemctl stop --user myunit

colo@ryzealot[ssh:A]:~ $ systemctl status --user myunit
Unit myunit.service could not be found.

Ich hoffe das illustriert ausreichend gut, wie man sich den fehleranfaelligen pkill-Tanz ersparen koennte.



Weiters: In Scripts, die via cron ausgefuehrt werden, tut man oft gut daran, PATH explizit zu setzen, sodass alle im Script verwendeten Tools auch sicher aufgerufen werden koennen.



Das ist erstmal alles, was mir zum geposteten Script einfaellt. Ich hoffe, es hilft einigen weiter :)

sichNix

Here to stay
Registered: Nov 2014
Location: 1230
Posts: 1069
Definitiv, vielen dank für die Erklärung!

davebastard

Vinyl-Sammler
Avatar
Registered: Jun 2002
Location: wean
Posts: 12296
ja thx, der hint mit systemd ist gut, den kannte ich noch nicht.
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz