Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ereignis in Logdatei soll Skript ausloesen

2 views
Skip to first unread message

Peter Blancke

unread,
Aug 5, 2022, 3:50:49 AM8/5/22
to
(Debian Linux Stable, Postfix)

Guten Tag,

ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
überwachen.

Also:

tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"

Sobald ein solcher Eintrag auftaucht, sehe ich den natürlich auf der
Konsole sofort. Nur... Da kann ich nicht den ganzen Tag davorsitzen.

Kann ich bei einem Fund auch ein Ereignis auslösen? Zum Beispiel:

tail -f /var/log/mail.log | \
grep "DAS WIRD GESUCHT" && mail -s "Ereignis gefunden" i...@example.org

Aber so funktioniert das nicht.

Per cron und grep würde gehen, ich müßte dann natürlich erkennen,
welche Ereigniss ich bereits gemeldet habe. Etwas umständlich.

Kann man dieses Problem einfacher lösen?

Gruß,

Peter Blancke

--
Hoc est enim verbum meum!

Bernd

unread,
Aug 5, 2022, 4:22:30 AM8/5/22
to
Am 05.08.22 um 09:50 schrieb Peter Blancke:
(...)
> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
> überwachen.
>
> Also:
>
> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>
> Sobald ein solcher Eintrag auftaucht, sehe ich den natürlich auf der
> Konsole sofort. Nur... Da kann ich nicht den ganzen Tag davorsitzen.
(...)

Ware inotify ein Schritt in die richtige Richtung?

Bernd

Markus Franzke

unread,
Aug 5, 2022, 4:24:19 AM8/5/22
to
Am 05.08.22 um 09:50 schrieb Peter Blancke:
Ich habe gerade von 'unbuffer' gelesen, das ich jedoch nicht einsetze,
und das offenbar auch nicht so richtig funktioniert.

Das einfachste wird sein, du setzt grep nicht auf eine Pipe an, sondern
auf eine jeweils bereits eingelesene Zeile. In _etwa_ so:

while read M; do echo $M | grep "MUSTER" && echo "TREFFER: $M"; done <
<(tail -f /var/log/messages)

wobei der Abschnitt »echo "TREFFER: $M"« durch dein »mail -s ...« zu
ersetzen wäre.

Ich würde zusätzlich statt -f lieber --follow=dateiname verwenden, damit
das Skript nach logrotate weitermachen kann.

M

Bernd

unread,
Aug 5, 2022, 4:25:39 AM8/5/22
to
Am 05.08.22 um 10:22 schrieb Bernd:
Hier <tm> heißt es iwatch:
iWatch monitor the filesystem's integrity in realtime and will send
alarm immediately to the system administrator when there is any changes
in the monitored filesystem. iWatch is written in Perl and based on
inotify, a file change notification system, a kernel feature that
allows applications to request the monitoring of a set of files against
a list of events.

Currently it can:
- run in command line mode as well as in daemon mode
- using an easy xml configuration file
- can watch directory recursively and watch new created directory
- can have a list of exceptions
- can use regex to compare the file/directory name
- can execute command if an event occures
- send email
- syslog
- print time stamp


Bernd


Peter Blancke

unread,
Aug 5, 2022, 4:46:28 AM8/5/22
to
Am 2022-08-05, Bernd <bna...@web.de> schrieb:
> Am 05.08.22 um 09:50 schrieb Peter Blancke:

>> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
>> überwachen.
>>
>> Also:
>>
>> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>>
>> Sobald ein solcher Eintrag auftaucht, sehe ich den natürlich auf der
>> Konsole sofort. Nur... Da kann ich nicht den ganzen Tag davorsitzen.


> Ware inotify ein Schritt in die richtige Richtung?

Ja, klar, das wäre es, aber zu aufwendig dafür, daß ich das nur
heute und/oder morgen brauche. Ich werde inotify nehmen, wenn ich
anderweitig nicht weiterkomme.

Ich schaue mir da nochmals den anderen Lösungsvorschlag an.

Danke.

Peter Blancke

unread,
Aug 5, 2022, 5:20:56 AM8/5/22
to
Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:

> while read M; do echo $M | grep "MUSTER" && echo "TREFFER: $M"; done <
><(tail -f /var/log/messages)

Moment...

Das bitte irgendwie noch zu befeilen.

Vereinfachte Versuche:

,----
| while read M; do echo $M done <<(tail -f /var/log/messages)
| -bash: Syntaxfehler beim unerwarteten Symbol »(«
|
| while read M; do echo $M done <(tail -f /var/log/messages)
| >
`----

Ich verstehe die Umleitung von tail an die while-Schleife leider
nicht.

Im zweiten Beispiel wartet der mit seinem ">" auf irgendwelche
Eingaben.

Ulli Horlacher

unread,
Aug 5, 2022, 5:21:08 AM8/5/22
to
Peter Blancke <bla...@gmx.de> wrote:

> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
> überwachen.
>
> Also:
>
> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>
> Sobald ein solcher Eintrag auftaucht, sehe ich den natürlich auf der
> Konsole sofort. Nur... Da kann ich nicht den ganzen Tag davorsitzen.

Und noch ein Problem:

Wenn logrotate zuschlaegt bekommt tailf das nicht mit und liest aus dem
falschen filehandle.

> Kann ich bei einem Fund auch ein Ereignis auslösen? Zum Beispiel:
>
> tail -f /var/log/mail.log | \
> grep "DAS WIRD GESUCHT" && mail -s "Ereignis gefunden" i...@example.org
>
> Aber so funktioniert das nicht.

Weil grep nicht terminiert und kein exit-status liefert, der vom &&
ausgewertet wird.


> Kann man dieses Problem einfacher lösen?

framstag@moep:~: ftailf -h
usage: ftailf [-t] ['[/pattern/[i]] [perl-code]'] file
options: -t flag each line with a time stamp
examples:
ftailf ~/Mail/.log
ftailf '/ssh/' /var/adm/messages
ftailf -t watchlog
ftailf '/spam/i system qq[sendmsg -qfs "$_" framstag\@bofh]' syslog&

Letztes Beispiel: das schickt eine message, wenn "spam" (egal ob
gross/klein) im syslog auftaucht.

ftailf ist logrotate-resistent.

https://fex.belwue.de/fstools/#ftailf


--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: horl...@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Markus Franzke

unread,
Aug 5, 2022, 5:24:43 AM8/5/22
to
Am 05.08.22 um 11:20 schrieb Peter Blancke:
Das ganze Konstrukt gehört natürlich in _eine_ Zeile.

Unsere schlauen Newsreader brechen es halt um.

Bei mir funktioniert das so.

M

Peter Blancke

unread,
Aug 5, 2022, 5:33:04 AM8/5/22
to
Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
> Am 05.08.22 um 11:20 schrieb Peter Blancke:
>> Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:

>> | while read M; do echo $M done <<(tail -f /var/log/messages)
>> | -bash: Syntaxfehler beim unerwarteten Symbol »(«
>> |
>> | while read M; do echo $M done <(tail -f /var/log/messages)
>> | >
>> `----

> Das ganze Konstrukt gehört natürlich in _eine_ Zeile.

Klar. Das habe ich natürlich -- wie gezeigt -- auch so gemacht.

Aber wie gesagt, beide Zeilen (mit einem "<" und mit zwei "<<")
gehen hier nicht, das erste wirft die Fehlermeldung und das zweite
wartet auf eine Eingabe.

> Bei mir funktioniert das so.

Mit der Bash?

Markus Franzke

unread,
Aug 5, 2022, 5:36:41 AM8/5/22
to
Am 05.08.22 um 11:33 schrieb Peter Blancke:
> Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
>> Am 05.08.22 um 11:20 schrieb Peter Blancke:
>>> Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
>
>>> | while read M; do echo $M done <<(tail -f /var/log/messages)
>>> | -bash: Syntaxfehler beim unerwarteten Symbol »(«
>>> |
>>> | while read M; do echo $M done <(tail -f /var/log/messages)
>>> | >
>>> `----
>
>> Das ganze Konstrukt gehört natürlich in _eine_ Zeile.
>
> Klar. Das habe ich natürlich -- wie gezeigt -- auch so gemacht.
>
> Aber wie gesagt, beide Zeilen (mit einem "<" und mit zwei "<<")
> gehen hier nicht, das erste wirft die Fehlermeldung und das zweite
> wartet auf eine Eingabe.
>
>> Bei mir funktioniert das so.
>
> Mit der Bash?
>
> Gruß,
>
> Peter Blancke
>

... done < <(tail ...

M

Peter Blancke

unread,
Aug 5, 2022, 5:54:49 AM8/5/22
to
Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:

>>>> | while read M; do echo $M done <<(tail -f /var/log/messages)

> ... done < <(tail ...

Tut mir leid, wenn's nervt.

Hier unter Bash ergibt das folgendes Bild:

,----
| blancke@server:~$ while read M; do echo $M done < <(tail -f /var/log/messages)
| > ^C
`----

Der Befehle wartet auf eine Eingabe, daher dann das ^C, ich hab's
abgebrochen.

Übersehe ich da irgendwas?

Markus Franzke

unread,
Aug 5, 2022, 5:59:51 AM8/5/22
to
Am 05.08.22 um 11:54 schrieb Peter Blancke:
Es nervt mich nicht.

Schreibe noch ein Semikolon (am besten mit Abstand) vor das "done", und
es läuft.

... echo $M; done < <(tail ...

M

Peter Blancke

unread,
Aug 5, 2022, 6:03:13 AM8/5/22
to
Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
> Am 05.08.22 um 11:54 schrieb Peter Blancke:

>> while read M; do echo $M done < <(tail -f /var/log/messages)

> Schreibe noch ein Semikolon (am besten mit Abstand) vor das
> "done", und es läuft.

Oha... *MIST* - "Das hätte nicht passieren dürfen!"(tm)

Gut, das geht.

Jetzt mache ich mit grep etc. weiter.

Danke.

Ulli Horlacher

unread,
Aug 5, 2022, 6:26:40 AM8/5/22
to
Peter Blancke <bla...@gmx.de> wrote:
> Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
> > Am 05.08.22 um 11:54 schrieb Peter Blancke:
>
> >> while read M; do echo $M done < <(tail -f /var/log/messages)
>
> > Schreibe noch ein Semikolon (am besten mit Abstand) vor das
> > "done", und es läuft.
>
> Oha... *MIST* - "Das hätte nicht passieren dürfen!"(tm)
>
> Gut, das geht.

Aber nur so lange kein logrotate laeuft.

Juergen Ilse

unread,
Aug 5, 2022, 6:43:31 AM8/5/22
to
Markus Franzke <opa-k...@web.de> wrote:
> Am 05.08.22 um 09:50 schrieb Peter Blancke:
>> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
>> überwachen.
>>
>> Also:
>>
>> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"

Daas kann nicht so funktionieren, wie du das moechtest, weil hier grep
nie beendet wird sondern immer weiter nach dem String sucht, auch wenn
er bereits einmal geefunden wurde.

>> Kann ich bei einem Fund auch ein Ereignis auslösen? Zum Beispiel:
>>
>> tail -f /var/log/mail.log | \
>> grep "DAS WIRD GESUCHT" && mail -s "Ereignis gefunden" i...@example.org
>>
>> Aber so funktioniert das nicht.

Natuerlich nichht. Die Mail wuerde erst gesendet, wenn sich grep beendet
haette *und* bis dahin den String mindestens einmal gefunden haette.
Da aber grep nicht beendet wird ...

>> Kann man dieses Problem einfacher lösen?

Du muesstest daafuer sorgen, dass nach jeder geprueften Zeile der "Such-
prozess" unnterbrochen wird, damit ein weiteres Kommando ausgefuehrt
werden koennte ...

Mir faellt da etwas wie:

tail -f /var/log/mail.log | while read line; do
case $line in
*"DAS WIRD GESUCHT"*)
mail -s "Ereignis gefunden" i...@example.org
;;
done

(ungetestet und ohne Gewaehr). Wenn der Suchbegriff rehular expressions
enthaelt und statt dessen zwingend grep verwendet werden soll, kann der
"case" Teil durch einen "if" Teil unter Verwendung von grep umgeschrie-
ben werden:

if grep "DAS WIRD GESUCHT" <(printf "%s" "$line")

> Ich habe gerade von 'unbuffer' gelesen, das ich jedoch nicht einsetze,
> und das offenbar auch nicht so richtig funktioniert.

Es funktioniert aus dem selben Grund nichht, wie der urspruengliche Versuch:
grep wird nicht beendet und das mail Kommando nie ausgefuehrt, bevor grep
beendet ist.

> Das einfachste wird sein, du setzt grep nicht auf eine Pipe an, sondern
> auf eine jeweils bereits eingelesene Zeile. In _etwa_ so:
>
> while read M; do echo $M | grep "MUSTER" && echo "TREFFER: $M"; done <
> <(tail -f /var/log/messages)

In die Richtung gehht auch meine Idee ...

> Ich würde zusätzlich statt -f lieber --follow=dateiname verwenden, damit
> das Skript nach logrotate weitermachen kann.

Das ist moeglicherweise eine gute Idee ...

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Juergen Ilse

unread,
Aug 5, 2022, 6:50:26 AM8/5/22
to
Hallo,

Peter Blancke <bla...@gmx.de> wrote:
> Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
>
>> while read M; do echo $M | grep "MUSTER" && echo "TREFFER: $M"; done <
>><(tail -f /var/log/messages)
>
> Moment...
>
> Das bitte irgendwie noch zu befeilen.
>
> Vereinfachte Versuche:
>
> ,----
> | while read M; do echo $M done <<(tail -f /var/log/messages)
> | -bash: Syntaxfehler beim unerwarteten Symbol »(«
> |
> | while read M; do echo $M done <(tail -f /var/log/messages)
> | >
> `----

Ja, das shell Konstrukt <<(command) existiert nicht, es muss <(command)
heiissen. Die Erklaerung findest du, wenn ddu in "man bash" nach "Process
Substitution" suchst.

> Ich verstehe die Umleitung von tail an die while-Schleife leider
> nicht.

Siehe oben: such in der man page nach "Process Substitution".

> Im zweiten Beispiel wartet der mit seinem ">" auf irgendwelche
> Eingaben.

Lass das Zeichen weg, das ist nur von einer "zitierten Leerzeile"
uebrig geblieben ...

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Peter Blancke

unread,
Aug 5, 2022, 6:53:53 AM8/5/22
to
Am 2022-08-05, Peter Blancke <bla...@gmx.de> schrieb:

Hier die (vorläufige?) Lösung mit Hintergrund des Problems:

> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
> überwachen.
>
> Also:
>
> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>
> Kann ich bei einem Fund auch ein Ereignis auslösen?

So, das Problem ist erst einmal wie folgt gelöst:

,----
|1 while read i; do
|2 echo $i | grep "DAS HIER SUCHE ICH" &&
|3 ( echo "KENNUNG0815 Meldung: $i " |
|4 telnet zuhause.example.com 11111 > /dev/null );
|5 done < <(tail -f /var/log/mail.log)
`----

Zeile 2:

Der Suchstring, wird gleichzeitig auf der Konsole ausgegeben, ggf.
mit "> /dev/null" unterdrücken.

Zeile 3:

Eine spezielle und nur mir bekannte Kennung
(Mißbrauchsverhinderung) und die Meldung werden...

Zeile 4:

...an meinen Rechner zu Hause auf Port 11111 gesendet, Ausgabe von
Telnet wird unterdrückt.

Per xinetd läuft auf meinem Rechner zu Hause auf dem Port ein
Dienst, der ruft ein Skript auf, das macht einen lokalen
Protokolleintrag inkl. Datumsstempel und ruft anschließend "beep"
in einer Dauerschleife auf. Schon schrecke ich vom Mittagsschl...,
äh, von der Arbeit hoch und weiß, jetzt heißt's eingreifen.

Zeile 5:

Muß ich erst noch verstehen. Dank an die Leute hier. Ach ja, tail
habe ich noch geändert, damit das auch ein Logrotate übersteht.

Hintergrund:

Seit zwei Tagen (03.08.2020) werden auf meinem Mailserver (bedient
einige zig Domains, KEINE Änderungen an der Konfiguration) einige
wenige Mails an Domains, deren MX bei outlook.com liegt, nicht mehr
angenommen, Ursache unbekannt. Mglw. bekannte Fehlermeldung:

,----
| Aug 5 11:41:33 mx1server postfix/smtp[1000650]:
| 42AB#######:
| to=<##################@#####.de>,
| relay=########.mail.protection.outlook.com[104.##.#.##]:25,
| delay=0.24, delays=0.03/0.01/0.18/0.02,
| dsn=5.7.606,
| status=bounced
| (host ########.mail.protection.outlook.com[104.##.#.##] said:
| 550 5.7.606 Access denied, banned sending IP [###.##.###.##].
| To request removal from this list please visit https://sender.office.com/
| and ...
`----

Warum das so ist? Keine Ahnung. Wer den Spaß auf
https://sender.office.com/ einmal mitgemacht hat, weiß, wie man
Lebenszeit verschwenden kann.

Da ich über einen zweiten MX verfüge, leite ich im Postfix des MX1
per "transport_maps" Mails an derartige Domains einfach auf MX2
weiter, dem outlook.com "noch" vertraut. So ist das Problem temporär
behoben.

Heute (05.08.2022) erzählt mir ein Kunde, er habe dieserthalben
seine Mail via GMX weiterleiten wollen und kriegt EXAKT die gleiche
Fehlermeldung. Toll.

Vielen Dank an alle hier, die mir weitergeholfen haben!

Juergen Ilse

unread,
Aug 5, 2022, 6:54:31 AM8/5/22
to
Hallo,
... und darauf achten, dass da wirklich ein Leerzeichen zwischen den
beiden "<", da die shell es sonst nicht schluckt ...

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Peter Blancke

unread,
Aug 5, 2022, 6:58:55 AM8/5/22
to
Am 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> schrieb:

>> Ich verstehe die Umleitung von tail an die while-Schleife leider
>> nicht.

> Siehe oben: such in der man page nach "Process Substitution".

Dankbar aufgegriffen.

Markus Franzke

unread,
Aug 5, 2022, 7:07:52 AM8/5/22
to
Am 05.08.22 um 12:53 schrieb Peter Blancke:
> Am 2022-08-05, Peter Blancke <bla...@gmx.de> schrieb:
>
> Hier die (vorläufige?) Lösung mit Hintergrund des Problems:
>
>> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
>> überwachen.
>>
>> Also:
>>
>> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>>
>> Kann ich bei einem Fund auch ein Ereignis auslösen?
>
> So, das Problem ist erst einmal wie folgt gelöst:
>
> ,----
> |1 while read i; do
> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
> |3 ( echo "KENNUNG0815 Meldung: $i " |
> |4 telnet zuhause.example.com 11111 > /dev/null );
> |5 done < <(tail -f /var/log/mail.log)
> `----

[...]

>
> Zeile 5:
>
> Muß ich erst noch verstehen. Dank an die Leute hier. Ach ja, tail
> habe ich noch geändert, damit das auch ein Logrotate übersteht.
>

Es wird (mit dem ersten '<') festgelegt, daß das Konstrukt "while ... do
... done" seine Eingabe nicht von STDIN beziehen soll, sondern von einer
anderen 'Quelle', die sich wie eine Datei verhalten wird.
Dann wird eine Subshell aufgerufen <(tail ...), deren STDOUT nach außen
zum Lesen so zur Verfügung gestellt wird, als handle es sich um das
Lesen aus einer Datei.
Alles keine Hexerei.

M

Peter Blancke

unread,
Aug 5, 2022, 7:11:27 AM8/5/22
to
Am 2022-08-05, Markus Franzke <opa-k...@web.de> schrieb:
> Am 05.08.22 um 12:53 schrieb Peter Blancke:

,----
| while read i; do
| [...]
| done < <(tail -f /var/log/mail.log)
`----

>> Muß ich erst noch verstehen.

> Es wird (mit dem ersten '<') festgelegt, daß das Konstrukt "while
> ... do ... done" seine Eingabe nicht von STDIN beziehen soll,
> sondern von einer anderen 'Quelle', die sich wie eine Datei
> verhalten wird.
> Dann wird eine Subshell aufgerufen <(tail ...), deren STDOUT nach
> außen zum Lesen so zur Verfügung gestellt wird, als handle es sich
> um das Lesen aus einer Datei.

Vielen, vielen Dank! Heute ist ein schöner Tag!

(Außer der Ärger mit outlook.com)

Helmut Waitzmann

unread,
Aug 5, 2022, 7:23:48 AM8/5/22
to
Peter Blancke <bla...@gmx.de>:

>ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
>überwachen.
>
>Also:
>
> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>
>Sobald ein solcher Eintrag auftaucht, sehe ich den natürlich auf der
>Konsole sofort. Nur... Da kann ich nicht den ganzen Tag davorsitzen.
>
>Kann ich bei einem Fund auch ein Ereignis auslösen? Zum Beispiel:
>
>
> tail -f /var/log/mail.log | \
> grep "DAS WIRD GESUCHT" && mail -s "Ereignis gefunden" i...@example.org
>
>Aber so funktioniert das nicht.
>

tail --follow=name --retry -- /var/log/mail.log |
{
while IFS= read -r -- zeile
do
if
printf '%s\n' "$zeile" |
grep -e '\<DAS WIRD GESUCHT\>' -q
then
printf '%s\n' "$zeile" |
mail -s 'Ereignis gefunden' -- i...@example.org
fi
done
}

Achtung!  Stell sicher, dass das Verschicken der Nachricht an dich
keinen Treffer in «/var/log/mail.log» verursacht, sonst hast du eine
Arbeitsbeschaffungsmaßnahme für dich und den Rechner.

Juergen Ilse

unread,
Aug 5, 2022, 7:24:06 AM8/5/22
to
Hallo,

Peter Blancke <bla...@gmx.de> wrote:
> ,----
> |1 while read i; do
> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
> |3 ( echo "KENNUNG0815 Meldung: $i " |
> |4 telnet zuhause.example.com 11111 > /dev/null );
> |5 done < <(tail -f /var/log/mail.log)
> `----

Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
vorrkaeme (ist bei Logs eher unwahrscheinlich), koennte es dichh dein
Home Verzeichnis einschliesslich aller Inhalte kosten ...

Du solltest mindestens das "$i" in Klammernn setzen, besser noch hier
printf %s "$line" verwenden. Um die Ausfuehrung von Teilen der Log
Meldung alss Kommando sicher auszuschliessen.

> Seit zwei Tagen (03.08.2020) werden auf meinem Mailserver (bedient
> einige zig Domains, KEINE Änderungen an der Konfiguration) einige
> wenige Mails an Domains, deren MX bei outlook.com liegt, nicht mehr
> angenommen, Ursache unbekannt. Mglw. bekannte Fehlermeldung:
>
> ,----
> | Aug 5 11:41:33 mx1server postfix/smtp[1000650]:
> | 42AB#######:
> | to=<##################@#####.de>,
> | relay=########.mail.protection.outlook.com[104.##.#.##]:25,
> | delay=0.24, delays=0.03/0.01/0.18/0.02,
> | dsn=5.7.606,
> | status=bounced
> | (host ########.mail.protection.outlook.com[104.##.#.##] said:
> | 550 5.7.606 Access denied, banned sending IP [###.##.###.##].
> | To request removal from this list please visit https://sender.office.com/
> | and ...
> `----

Sieht danach aus, als waere deine IP-Adresse "geblacklisted". Warum folgst
du nicht dem Vorschlag, dir mal https://sender.office.com/ anzusehen?

> Warum das so ist? Keine Ahnung. Wer den Spaß auf
> https://sender.office.com/ einmal mitgemacht hat, weiß, wie man
> Lebenszeit verschwenden kann.

Du wirst das Problem immer wieder haben, olange die IP-Adresse nicht
von der Blacklist entfernt wurde. Die Seite enthaelt wohl die Anleitung,
wie man das beantragt. Wenn M$ weiterhin der Meinung ist, dass von der
IP-Adresse Muell eingeliefert wird, wird das allerdings nicht erfolgreich
sein ...

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Peter Blancke

unread,
Aug 5, 2022, 7:54:41 AM8/5/22
to
Am 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> schrieb:
> Peter Blancke <bla...@gmx.de> wrote:

>> |1 while read i; do
>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>> |4 telnet zuhause.example.com 11111 > /dev/null );
>> |5 done < <(tail -f /var/log/mail.log)

> Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
> Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
> vorrkaeme (ist bei Logs eher unwahrscheinlich),

Ja, ist unwahrscheinlich. Aber trotzdem, aus Prinzip richtig machen.
Ich habe es eingebaut:

,----
| 3 ( printf %s "KENNUNG0815 Meldung: $i" |
| 4 telnet zuhause.example.com 11111 > /dev/null );
`----

Ferner habe ich die Sache latürnich dadurch abgesichert, daß ich den
Kennungsstring verwende (was allerdings noch NICHT schützt, sondern
nur Spielkinder verägert, die nichts sehen, egal, was sie
eintippen). Und außerdem lauscht der Xinetd AUSSCHLIESSLICH auf der
IP meines Servers ("only_from").

Was ist damit gemeint, $i in Klammern zu setzen? Was bewirkt das?

>> | (host ########.mail.protection.outlook.com[104.##.#.##] said:
>> | 550 5.7.606 Access denied, banned sending IP [###.##.###.##].
>> | To request removal from this list please visit https://sender.office.com/
>> | and ...

> Sieht danach aus, als waere deine IP-Adresse "geblacklisted".
> Warum folgst du nicht dem Vorschlag, dir mal
> https://sender.office.com/ anzusehen?

Wie geschrieben: Verschwendete Lebenszeit.

Habe ich. Da kommt auch ein Bestätigungslink an meine Adresse. Wenn
ich da drauf klicke, erhalte ich als Meldung, der Link sei bereits
erloschen -- dabei habe ich innerhalb von 20 Sekunden reagiert.
Hab's mehrfach versucht.

Für mich ist das Bösartigkeit. Zu diesem Fehler finde ich viele
öhnlich lautende Berichte im Netz.

Gut, ich werde das kommende Woche ggf. nochmals versuchen.

Helmut Waitzmann

unread,
Aug 5, 2022, 8:23:36 AM8/5/22
to
Peter Blancke <bla...@gmx.de>:
>|1 while read i; do
>|2 echo $i | grep "DAS HIER SUCHE ICH" &&
>|3 ( echo "KENNUNG0815 Meldung: $i " |
>|4 telnet zuhause.example.com 11111 > /dev/null );
>|5 done < <(tail -f /var/log/mail.log)

[…]

>Zeile 5:
>
> Muß ich erst noch verstehen. Dank an die Leute hier.

(Übrigens:  Dein Text ist vorbildlich:  Du zeigst ein Kommando,
numerierst dabei die Zeilen und beziehst dich in den Kommentaren auf
die Zeilennummern.  Das ist echter Service für die Antwortenden.)


Das Bash‐Konstrukt


while …

done < <( ein Kommando )

erzeugt ein FIFO (oder pipe), das einen Dateinamen hat.  Wie der
heißt, bleibt (zunächst) das Geheimnis des Shells.

Der Shell öffnet das FIFO zum Schreiben und gibt den dabei
erhaltenen Dateideskriptor dem Shell, der «ein Kommando» ausführt,
als Standardausgabe.  => «ein Kommando» schreibt in das FIFO.

Die Eingabeumlenkung hinter der «while»‐Schleife öffnet das FIFO
mittels seines Dateinamens zum Lesen und gibt den dabei erhaltenen
Dateideskriptor der «while»‐Schleife als Standardeingabe.

(Wie der Dateiname des FIFOs aussieht, spielt dabei keine Rolle.) 
Aber natürlich ist es interessant und macht das Verstehen griffiger,
wenn man ihn mal sehen könnte.


Probier dazu mal das folgende Kommando:


sh -c -- 'ls -dl -- "$1" ; ls -dl -L -- "$1"' sh <( true )


«sh» erhält als letzten Parameter einen Dateinamen des mit


<( true )»

erzeugten FIFOs.  Der Parameter ist innerhalb der dem «sh» hinter
«-c --» übergebenen Kommandozeile als «"$1"» verfügbar.

«sh -c» öffnet natürlich seine ihm als Parameter übergebenen
Dateinamen nicht, deshalb ist das Kommando zunächst nicht sehr
geistreich, aber «ls» zeigt Dateinamen an.  Probiere es aus und
sieh, welchen Dateinamen das FIFO hat.

Ich nehme hier zwei «ls»‐Kommandos, einmal ohne und einmal mit «-L»
für den Fall, dass der Dateiname ein symbolic link bezeichnet, damit
man sowohl den Namen des symbolic links als auch das Ziel des
symbolic links sehen kann.

Das in den runden Klammern stehende Kommando «true» schreibt
nichts in seine Standardausgabe; es kommt nur fehlerfrei zu Ende.


Nochmal zurück zu


while …

done < <( ein Kommando )


Der Name des FIFOs wird also nur vom Shell intern verwendet: um es
für die «while»‐Schleife zum Lesen zu öffnen und zur Standardeingabe
zu machen, und, um es für «ein Kommando» zum Schreiben zu öffnen und
zur Standardausgabe zu machen.  Könnte man da den Dateinamen nicht
einsparen?  Ja, man kann:

ein Kommando |
while …

done

Diese Variante kommt ohne die «bash»‐spezifische
Prozess‐Substitution aus und verwendet nur die in jedem zum
POSIX‐Standard kompatiblen Shell vorhandenen Möglichkeiten. 
Außerdem muss sie keinen Dateinamen ins Dateisystem stellen.

--
Hat man erst verstanden, wie Unix funktioniert, ist auch
das Shell-Handbuch kein Buch mit sieben Siegeln mehr.

Christian Weisgerber

unread,
Aug 5, 2022, 8:30:06 AM8/5/22
to
On 2022-08-05, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

>> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>
> Wenn logrotate zuschlaegt bekommt tailf das nicht mit und liest aus dem
> falschen filehandle.

Kommt auf das tail(1) an. Ich hätte hier ein tail, welches das sehr
wohl erkennt, und neban eines, dem man das mit -F sagen kann.

--
Christian "naddy" Weisgerber na...@mips.inka.de

Christian Weisgerber

unread,
Aug 5, 2022, 9:30:05 AM8/5/22
to
On 2022-08-05, Helmut Waitzmann <nn.th...@xoxy.net> wrote:

> while …
> …
> done < <( ein Kommando )
>
> Könnte man da den Dateinamen nicht einsparen?  Ja, man kann:
>
> ein Kommando |
> while …
> …
> done
>
> Diese Variante kommt ohne die «bash»‐spezifische
> Prozess‐Substitution aus und verwendet nur die in jedem zum
> POSIX‐Standard kompatiblen Shell vorhandenen Möglichkeiten. 

Letzteres führt die while-Schleife in einer Subshell aus, was für
das Problem in diesem Thread keine Rolle spielt, bei anderen schon.

Eine weitere, POSIX-kompatible Möglichkeit ohne Subshell:

while …

done <<EOF
$(ein Kommando)
EOF

Helmut Waitzmann

unread,
Aug 5, 2022, 11:23:04 AM8/5/22
to
Christian Weisgerber <na...@mips.inka.de>:
>On 2022-08-05, Helmut Waitzmann <nn.th...@xoxy.net> wrote:
>
>> while …
>> …
>> done < <( ein Kommando )
>>
>> Könnte man da den Dateinamen nicht einsparen?  Ja, man kann:
>>
>>
>> ein Kommando |
>> while …
>> …
>> done
>>
>> Diese Variante kommt ohne die «bash»‐spezifische
>> Prozess‐Substitution aus und verwendet nur die in jedem zum
>> POSIX‐Standard kompatiblen Shell vorhandenen Möglichkeiten. 
>
>Letzteres führt die while-Schleife in einer Subshell aus, was für
>das Problem in diesem Thread keine Rolle spielt, bei anderen schon.

Ja.

>Eine weitere, POSIX-kompatible Möglichkeit ohne Subshell:
>
>
> while …
> …
> done <<EOF
> $(ein Kommando)
> EOF

Das hat bei meinen Shells («dash» und «bash» auf Debian 10)
allerdings den Nachteil, dass die «while»‐Schleife erst losläuft,
wenn das Here‐Document zum Ende gekommen ist:

while IFS= read -r zeile
do
printf '%25s ' "$zeile"
date -- '+%Y-%m-%dT%T%:z'
done <<-EOF
$( date -- '+%Y-%m-%dT%T%:z' )
$( sleep -- 2 )
$( date -- '+%Y-%m-%dT%T%:z' )
EOF

Das sieht mir nach einer temporären Datei statt nach einem FIFO aus.

Peter Blancke

unread,
Aug 5, 2022, 1:52:30 PM8/5/22
to
Am 2022-08-05, Peter Blancke <bla...@gmx.de> schrieb:
> Am 2022-08-05, Peter Blancke <bla...@gmx.de> schrieb:

>> ich muß die /var/log/mail.log auf einen bestimmten Eintrag hin
>> überwachen.
>>
>> Also:
>>
>> tail -f /var/log/mail.log | grep "DAS WIRD GESUCHT"
>>
>> Kann ich bei einem Fund auch ein Ereignis auslösen?

> So, das Problem ist erst einmal wie folgt gelöst:
>
>|1 while read i; do
>|2 echo $i | grep "DAS HIER SUCHE ICH" &&
>|3 ( echo "KENNUNG0815 Meldung: $i " |
>|4 telnet zuhause.example.com 11111 > /dev/null );
>|5 done < <(tail -f /var/log/mail.log)

Recte:

Zeile 5:

done < <(tail -F /var/log/mail.log)

Und jetzt das Wunder /ohne weiteres Zutun von mir/:

Nachdem ich mit all diesen Studien durch war, klappt der
Zustellversuch über

,----[ Aus: /var/log/mail.log (Postfix) 3.5.13-0+deb11u1 ]
| relay=###############-de01c.mail.protection.outlook.com[104.47.##.##]:25
`----

plötzlich seit ca. heute 18 Uhr wieder problemlos und zwar für alle
39 Domains, die ich im Laufe des Tages Stück für Stück über den MX2
*händisch* umleiten mußte. Ursache weiterhin unbekannt, aber mich
erleichtert's nicht unerheblich.

Nochmals herzlichen Dank an alle für die zahlreichen Anregungen und
Hilfen, so hat der Tag *mir* wenigstens durch Lernen Spaß und
Erkenntnis gebracht!

Laurenz Trossel

unread,
Aug 5, 2022, 1:55:32 PM8/5/22
to
On 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> wrote:
> Peter Blancke <bla...@gmx.de> wrote:
>> ,----
>> |1 while read i; do
>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>> |4 telnet zuhause.example.com 11111 > /dev/null );
>> |5 done < <(tail -f /var/log/mail.log)
>> `----
>
> Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
> Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
> vorrkaeme (ist bei Logs eher unwahrscheinlich), koennte es dichh dein
> Home Verzeichnis einschliesslich aller Inhalte kosten ...

Wie funktioniert das?

# i='$(rm -rfv /tmp/foo)'
# echo $i
$(rm -rfv /tmp/foo)

Ich benutze aus Gewohnheit "${i}" aber es würde mich interessieren, wie es
in o.a. Script zu dem von dir befürchteten Szenario kommt.

> Sieht danach aus, als waere deine IP-Adresse "geblacklisted". Warum folgst
> du nicht dem Vorschlag, dir mal https://sender.office.com/ anzusehen?

Outlook nimmt mal Mail an und mal nicht. Das ist einfach so.

Markus Franzke

unread,
Aug 5, 2022, 1:58:13 PM8/5/22
to
Am 05.08.22 um 19:55 schrieb Laurenz Trossel:
> On 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> wrote:
>> Peter Blancke <bla...@gmx.de> wrote:
>>> ,----
>>> |1 while read i; do
>>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>>> |4 telnet zuhause.example.com 11111 > /dev/null );
>>> |5 done < <(tail -f /var/log/mail.log)
>>> `----
>>
>> Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
>> Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
>> vorrkaeme (ist bei Logs eher unwahrscheinlich), koennte es dichh dein
>> Home Verzeichnis einschliesslich aller Inhalte kosten ...
>
> Wie funktioniert das?
>
> # i='$(rm -rfv /tmp/foo)'
> # echo $i
> $(rm -rfv /tmp/foo)
>
> Ich benutze aus Gewohnheit "${i}" aber es würde mich interessieren, wie es
> in o.a. Script zu dem von dir befürchteten Szenario kommt.
>

Nimm einmal doppelte Anführungszeichen statt Apostrophe.

M

Laurenz Trossel

unread,
Aug 5, 2022, 2:04:37 PM8/5/22
to
On 2022-08-05, Markus Franzke <opa-k...@web.de> wrote:
> Am 05.08.22 um 19:55 schrieb Laurenz Trossel:
>> On 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> wrote:
>>> Peter Blancke <bla...@gmx.de> wrote:
>>>> ,----
>>>> |1 while read i; do
>>>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>>>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>>>> |4 telnet zuhause.example.com 11111 > /dev/null );
>>>> |5 done < <(tail -f /var/log/mail.log)
>>>> `----
>>>
>>> Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
>>> Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
>>> vorrkaeme (ist bei Logs eher unwahrscheinlich), koennte es dichh dein
>>> Home Verzeichnis einschliesslich aller Inhalte kosten ...
>>
>> Wie funktioniert das?
>>
>> # i='$(rm -rfv /tmp/foo)'
>> # echo $i
>> $(rm -rfv /tmp/foo)
>
> Nimm einmal doppelte Anführungszeichen statt Apostrophe.

Dann wird es bereits bei der Zuweisung ausgeführt. Das ist nicht, wovor
Juergen warnt, oder doch?

# echo '$(rm -rfv /tmp/foo)'|while read i; do echo $i; done
$(rm -rfv /tmp/foo)

Markus Franzke

unread,
Aug 5, 2022, 2:23:04 PM8/5/22
to
Am 05.08.22 um 20:04 schrieb Laurenz Trossel:
Die 'Zuweisung' erfolgt bei 'read i' und ist nicht das Problem.

So könnte in i also der String »123 $(echo ABC) 789« stehen. Ohne
irgendwelche Anführungszeichen vorne und hinten.

Wenn es beim Abrufen des Inhaltes in einem '"' Zusammenhang verwendet
wird, erfolgt die Ausführung des echo Befehls, der natürlich auch ein rm
oder dd sein könnte. Desgleichen auch in einem Zusammenhang ganz ohne
einfache oder doppelte Anführungszeichen.

Wenn der Abruf in einem "'" Zusammenhang erfolgt, wird der
Originalinhalt »123 $(echo ABC) 789« ausgegeben.

Man könnte generell verdächtige Inhalte dadurch entschärfen, daß man sie
quoten läßt, also ähnlich wie 'htmlspecialchars' in PHP. Das kann man
z.B. mit "${i@Q}" erledigen.

M

Laurenz Trossel

unread,
Aug 5, 2022, 2:36:25 PM8/5/22
to
On 2022-08-05, Markus Franzke <opa-k...@web.de> wrote:

> Die 'Zuweisung' erfolgt bei 'read i' und ist nicht das Problem.
>
> So könnte in i also der String »123 $(echo ABC) 789« stehen. Ohne
> irgendwelche Anführungszeichen vorne und hinten.
>
> Wenn es beim Abrufen des Inhaltes in einem '"' Zusammenhang verwendet
> wird, erfolgt die Ausführung des echo Befehls, der natürlich auch ein rm
> oder dd sein könnte. Desgleichen auch in einem Zusammenhang ganz ohne
> einfache oder doppelte Anführungszeichen.

Und genau das kriege ich nicht reproduziert. Hast du dafür ein Beispiel?
Ich möchte auch mal hacken ;-)

# cat | while read i; do echo "$i"; done
123 $(echo ABC) 789
123 $(echo ABC) 789

> Man könnte generell verdächtige Inhalte dadurch entschärfen, daß man sie
> quoten läßt, also ähnlich wie 'htmlspecialchars' in PHP. Das kann man
> z.B. mit "${i@Q}" erledigen.

Ich benutze "${x}", weil es damit keine unerwarteten Effekte mit
Variablennamen gibt, z.B. in "${i}100".

Markus Franzke

unread,
Aug 5, 2022, 2:50:13 PM8/5/22
to
Am 05.08.22 um 20:36 schrieb Laurenz Trossel:

>
> Und genau das kriege ich nicht reproduziert. Hast du dafür ein Beispiel?
> Ich möchte auch mal hacken ;-)
>
> # cat | while read i; do echo "$i"; done
> 123 $(echo ABC) 789
> 123 $(echo ABC) 789

Da hatte ich tatsächlich ein anderes Verhalten erwartet. Vielleicht kann
jemand anders zur Erhellung beitragen?

>
> Ich benutze "${x}", weil es damit keine unerwarteten Effekte mit
> Variablennamen gibt, z.B. in "${i}100".

Das mache ich fast überall genauso.

M

Juergen Ilse

unread,
Aug 5, 2022, 3:33:02 PM8/5/22
to
Hallo,

Markus Franzke <opa-k...@web.de> wrote:
> Am 05.08.22 um 20:36 schrieb Laurenz Trossel:
>
>>
>> Und genau das kriege ich nicht reproduziert. Hast du dafür ein Beispiel?
>> Ich möchte auch mal hacken ;-)
>>
>> # cat | while read i; do echo "$i"; done
>> 123 $(echo ABC) 789
>> 123 $(echo ABC) 789
>
> Da hatte ich tatsächlich ein anderes Verhalten erwartet. Vielleicht kann
> jemand anders zur Erhellung beitragen?

Ein "echo" reicht dafuer nichht aus, aber wenn man es ssich nicht angewoehnt,
moeglichst immer passend zu quoten, kann das ganze irgenwann mal (z.B. bei
Verwendung von "eval") einmal nacch hhinten losgehen.

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Helmut Waitzmann

unread,
Aug 6, 2022, 10:35:03 AM8/6/22
to
Juergen Ilse <ne...@usenet-verwaltung.de>:
>Peter Blancke <bla...@gmx.de> wrote:
>> ,----
>> |1 while read i; do
>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>> |4 telnet zuhause.example.com 11111 > /dev/null );
>> |5 done < <(tail -f /var/log/mail.log)
>> `----
>
>Das koennte gefaehrlich sein, wenn die eingelesene Zeile unerwartete
>Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm -rf $HOME)" darin
>vorrkaeme (ist bei Logs eher unwahrscheinlich), koennte es dichh dein
>Home Verzeichnis einschliesslich aller Inhalte kosten ...


Nein, so gefährlich ist es nicht.


echo $i


ist etwas anderes als das sehr gefährliche


eval echo "$i"


Am genauesten ist Variablenexpansion mit und ohne Anführungszeichen
im POSIX‐Standard
(<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06>)
beschrieben.  Mach dir die Mühe, ihn zu lesen.  Es lohnt sich.

Ganz kurz:  «"$i"» nimmt den Inhalt der Variablen und stellt ihn als
einen Aufrufparameter dem sogen. simple command (hier: «echo») zur
Verfügung.  «$i» nimmt den Inhalt der Variablen, zersägt ihn an den
in der Shell‐Variablen «IFS» aufgezählten Zeichen und stellt die
Bruchstücke als mehrere Aufrufparameter dem «echo» zur Verfügung. 
(Wenn der Inhalt der Variablen «i» nur aus IFS‐Zeichen besteht, kann
es auch passieren, dass kein einziger Aufrufparameter mehr übrig
bleibt.)  Entstehen beim Zersägen Dateinamensmuster, kann auch noch
Pathname Expansion (siehe
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_06>)
passieren.

Probiere es aus – man muss ja nicht mit dem Feuer spielen, deshalb
«ls» statt «rm»:

(
i='$( ls -ld -- $HOME )'

# set -x bewirkt, dass die simple commands
# unmittelbar vor der Ausfuehrung angezeigt werden:
#
set -x
printf '%s\n' "$i"
printf '%s\n' $i
eval printf '%s\n' "$i"
)

>Du solltest mindestens das "$i" in Klammernn setzen,
>

Wo siehst du hier eine Notwendigkeit, Klammern zu verwenden?


>besser noch hier printf %s "$line" verwenden.
>

Das ist immer eine gute Idee, «printf» zu verwenden, wenn man die
Unwägbarkeiten von «echo» nicht haben will.  (Ich kann mir keinen
Fall vorstellen, wo man sie haben wollte.)

>Um die Ausfuehrung von Teilen der Log Meldung alss Kommando sicher
>auszuschliessen.

«$i» statt «"$i"» führt nicht zu unerwarteter Neuinterpretation des
Variableninhalts als Kommandozeile.  Das tun nur «eval» und andere
Möglichkeiten, wo man einen Text einem Shell als Kommandozeile
vorlegt, beispielsweise:

ein Kommando, das etwas ausgibt | sh

sh -c -- "$i"

sh <( ein Kommando, das etwas ausgibt )

Von so etwas muss man die Finger lassen, es sei denn, man weiß mit
Sicherheit (beispielsweise, weil man sie selber erzeugt hat), welche
Daten dem Shell als Kommandozeile vorgelegt werden.

Helmut Waitzmann

unread,
Aug 6, 2022, 12:46:29 PM8/6/22
to
Laurenz Trossel <m...@example.invalid>:
>On 2022-08-05, Markus Franzke <opa-k...@web.de> wrote:
>> Am 05.08.22 um 19:55 schrieb Laurenz Trossel:
>>> On 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> wrote:
>>>> Peter Blancke <bla...@gmx.de> wrote:
>>>>> ,----
>>>>> |1 while read i; do
>>>>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>>>>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>>>>> |4 telnet zuhause.example.com 11111 > /dev/null );
>>>>> |5 done < <(tail -f /var/log/mail.log)
>>>>> `----
>>>>
>>>> Das koennte gefaehrlich sein, wenn die eingelesene Zeile
>>>> unerwartete Zeichenkennten enthaelt ... Wenn z.B. etwas wie
>>>> "$(rm -rf $HOME)" darin vorrkaeme (ist bei Logs eher
>>>> unwahrscheinlich), koennte es dichh dein Home Verzeichnis
>>>> einschliesslich aller Inhalte kosten ...
>>>
>>> Wie funktioniert das?
>>>
>>> # i='$(rm -rfv /tmp/foo)'
>>> # echo $i
>>> $(rm -rfv /tmp/foo)
>>
>> Nimm einmal doppelte Anführungszeichen statt Apostrophe.
>
>Dann wird es bereits bei der Zuweisung ausgeführt.
>

Du hast völlig recht.


>Das ist nicht, wovor Juergen warnt, oder doch?
>

Auch da hast du völlig recht:  Das ist nicht das, wovor Juergen
warnt.  (Juergen sieht da eine Gefahr, die es dort nicht gibt.)

Helmut Waitzmann

unread,
Aug 6, 2022, 12:47:51 PM8/6/22
to
Laurenz Trossel <m...@example.invalid>:
>On 2022-08-05, Juergen Ilse <ne...@usenet-verwaltung.de> wrote:
>> Peter Blancke <bla...@gmx.de> wrote:
>>> ,----
>>> |1 while read i; do
>>> |2 echo $i | grep "DAS HIER SUCHE ICH" &&
>>> |3 ( echo "KENNUNG0815 Meldung: $i " |
>>> |4 telnet zuhause.example.com 11111 > /dev/null );
>>> |5 done < <(tail -f /var/log/mail.log)
>>> `----
>>
>> Das koennte gefaehrlich sein, wenn die eingelesene Zeile
>> unerwartete Zeichenkennten enthaelt ... Wenn z.B. etwas wie "$(rm
>> -rf $HOME)" darin vorrkaeme (ist bei Logs eher unwahrscheinlich),
>> koennte es dichh dein Home Verzeichnis einschliesslich aller
>> Inhalte kosten ...
>
>Wie funktioniert das?
>
>
># i='$(rm -rfv /tmp/foo)'
># echo $i
>$(rm -rfv /tmp/foo)
>

Wie du vermutest und dein Versuch zeigt, funktioniert es nicht. 
Funktionieren würde

i='$(rm -rfv /tmp/foo)'
eval echo "$i"

obwohl bei der Zuweisung an die Variable «i» Apostrophe und bei der
Auswertung der Variablen «i» Anführungszeichen verwendet werden, und
zwar aus folgendem Grund:

Mit «eval» lässt der Shell den Kommandozeilen‐Parser auf die bereits
geparste Kommandozeile los.  Im einzelnen geschieht folgendes:


Zunächst parst der Shell – wie gewohnt – die Kommandozeile


eval echo "$i"


und erkennt dabei, dass es sich bei dem Kommando in der
Kommandozeile um ein sogenanntes «simple command», also um ein
einfaches Kommando, das keine weiteren Konstrukte (compound
commands) wie «if», «while», «until» und «for», keine geklammerten
Kommandos wie «( … )» und «{ … }» (grouping commands), keine
bedingten Kommandos wie « … && …» und «… || …» und keine Pipes «… |
…» verwendet, handelt.

Ein simple command wird verarbeitet, indem die Kommandozeile in
Wörter zerlegt wird.  Variablenzuweisungen und Ein‐ und
Ausgabeumlenkungen (beide in diesem Beispiel nicht enthalten) werden
speziell verarbeitet.  Dann wird das erste Wort (also das ganz
links) darauf hin untersucht, ob es der Name eines Aliasses, einer
Shell‐Funktion, eines in den Shell eingebauten Kommandos oder eines
externen Programms ist.

Ist es der Name eines externen Programms, erzeugt der Shell eine
Prozesskopie von sich selbst (mit dem Systemaufruf «fork»); die
Shell‐Prozesskopie schließlich startet den Systemaufruf «execve» und
übergibt ihm als Parameter den Dateinamen der Programmdatei (damit
«execve» weiß, welches Programm es laden und starten soll) und eine
Parameterliste für das zu startende Programm, die aus dem
Namen des Programms als ersten Parameter (damit das laufende
Programm sehen kann, wie es heißt) und allen weiteren Wörtern
ebenfalls als je einzelnen Parameter besteht.

Ist das erste Wort der Kommandozeile kein externes Programm sondern
wird vom Shell selbst ausgeführt, tut der Shell nur so, als wäre es
ein externes Programm:  «fork» und «execve» unterbleiben, aber das
Errichten einer Parameterliste wird wie oben durchgeführt, und der
Shell erledigt die Aufgabe des Kommandos anschließend selbst.

Aus

eval echo "$i"

entsteht also das simple command mit dem Namen «eval» und den beiden
zusätzlichen Parametern «echo» und «$(rm -rfv /tmp/foo)».  Und jetzt
kommt die Semantik von «eval» ins Spiel:

«eval» klebt alle seine Parameter mit je einer Leerstelle zwischen
den einzelnen Parametern zusammen.  So entsteht der folgende Text:

«echo $(rm -rfv /tmp/foo)»


Und dann lässt es den Shell‐Parser auf den Text los, nimmt ihn also
als Kommandozeile her.  Damit wird

«echo $(rm -rfv /tmp/foo)»

als Kommandozeile zerlegt und interpretiert.


Dass die Kommandozeile


echo $(rm -rfv /tmp/foo)

gefährlich ist – habe ich aus den Beiträgen hier den Eindruck – hat
jeder verstanden, richtig?  (Falls nicht, fragt nach.)
0 new messages