Martin-MS Sorry, ich muss das immer erst nachlesen...
Das hatte ich garnicht verstanden, weil ich nur die /etc/hosts monitored hatte. Da das Skript zuerst nach /tmp und dann nach /etc/hosts kopiert ist mir nicht aufgefallen, das wohl tatsächlich eine "hosts2" angelegt wurde. Die Option -O hosts habe ich eingefügt (wget) und das Skript abgeändert:

#!/bin/sh

# Make sure we're running as root
if 
(( `id -u` != 0 )); then { echo "Sie haben keine Root Rechte, beende..."; exit; } 
fi

cd /tmp
wget -O hosts https://hosts.ubuntu101.co.za/hosts
head -400 hosts | grep --quiet ^127.0.0.1
if (( $? != 0 )); then
   echo "Error: Falsche hosts Download-Liste"
   exit 1
else
   mv hosts /etc/hosts
fi

Das Problem liegt leider am DNS Server. Ich habe in meiner Fritzbox den DNS-Server von "Cloudflare" und "DNS over TLS (DoT)" eingerichtet. Dies führt dazu, dass die Namensauflösung temporär nicht funktioniert.

Wenn ich das Skript oder den *.service manuell starte, funktioniert es komischerweise fehlerfrei bei der Namensauflösung. Wenn ich in der Fritzbox-config den DNS-Server auf "Vom Internetanbieter zugewiesene DNSv4-Server verwenden (empfohlen)" ändere, funktioniert das ganze per *.timer oder *.service ebenfalls problemlos.

Ich lasse den *.timer & *.service jetzt weg und starte das Skript manuell, da ich nicht auf den DNS-Server und "DNS over TLS (DoT)" verzichten möchte.

  • GerBra hat auf diesen Beitrag geantwortet.

    Hast du es denn auch mal mit curl versucht? Da die vorhandenen Inhalte von /etc/hosts sowieso überschrieben werden, könnte man die Aufgabe auch mit einem Einzeiler erledigen:

    curl https://hosts.ubuntu101.co.za/hosts | grep '^127.0.0.1\|^255.255.255.255\|^::1\|^fe80\|^0.0.0.0' >/etc/hosts

    Die Überprüfung auf den root-Benutzer ist bei Ausführung als system unit entbehrlich, und auf die Plausibilitätsprüfung kann wegen des grep-Filters eigentlich auch verzichtet werden.

    Was mir bei meinen Tests allerdings auffiel war, dass systemd-resolved Hostnamen mit Unterstrich als ungültig zurück weist und für jeden dieser Hostnamen (wovon es aktuell 856 gibt) zwei Zeilen im journal ablegt. Das passiert bei jeder DNS-Anfrage und dürfte so das Journal ziemlich zumüllen. Wenn du einen anderen Resolver verwendest, ist das vielleicht egal, aber ein Blick dazu ins journal wäre trotzdem angezeigt.

    Außerdem dürfte ein solcher Eintrag dann auch nicht auf 0.0.0.0umgeleitet werden, was dann den eigentlichen Nutzen der Liste zweifelhaft erscheinen lässt, denn für diese Einträge wird der Hostname dann doch in seine eigentlich Adresse aufgelöst und die Verbindung hergestellt.

    • GerBra hat auf diesen Beitrag geantwortet.

      fdell Das Problem liegt leider am DNS Server. Ich habe in meiner Fritzbox den DNS-Server von "Cloudflare" und "DNS over TLS (DoT)" eingerichtet. Dies führt dazu, dass die Namensauflösung temporär nicht funktioniert.

      Wenn ich das Skript oder den *.service manuell starte, funktioniert es komischerweise fehlerfrei bei der Namensauflösung. Wenn ich in der Fritzbox-config den DNS-Server auf "Vom Internetanbieter zugewiesene DNSv4-Server verwenden (empfohlen)" ändere, funktioniert das ganze per *.timer oder *.service ebenfalls problemlos.

      Es könnte einfach sein, daß die TLS-Session zu deinem Nameserver abgelaufen wäre zu diesem Zeitpunkt. Und wget/curl versuchen dann nur einmal, eine IP-Adresse für den Download zu erhalten.
      Möglichkeiten:
      a) Den wget-Aufruf mehrmals zu starten, z.B. in einer for-Schleife dreimal mit 1 Sekunde Pause. Die Schleife kann abgebrochen werden wenn der Return-Wert von wget 0/erfolgreich ist.
      b) Evtl. reicht schon ein vorheriger DNS-Request um die Session zum DNS-Server zu initiieren. Z.B. durch ein vorangehendes:

      ping -c 3 hosts.ubuntu101.co.za
      sleep 1

      (Die ping-Ausgabe kann - wenn es so klappt - komplett nach /dev/null umgeleitet werden.)

      Fakt ist auf jedenfall: Da das Downloaden der Liste ja der zentrale Vorgang des Skripts ist, bedarf dieser eine eigene "Fehler"-Behandlung und sollte nur dann abbrechen(nichts tun), wenn der User bestimmte Kriterien als nicht möglich ersieht.

      Leider (aber in punkto Sicherheit zum Glück) erlauben weder wget noch curl andere DNS-Server für die Aktion zu verwenden, beide Tools sind ohne die entsprechende Option kompiliert. Dann könnte z.B. für diesen Aufruf dein Provider DNS verwendet werden anstatt des System-DNS. Es wäre allerdings möglich sich bei Bedarf ein eigenes (ggf. statisch gelinktes) wget/curl zu bauen und z.B. nach /usr/local abzulegen. Das wäre aber IMHO mit "Kanonen auf Spatzen" gefeuert und bedarf auch einiger Sicherheitsvor-/nachkehrungen.

      Martin-MS Außerdem dürfte ein solcher Eintrag dann auch nicht auf 0.0.0.0umgeleitet werden, was dann den eigentlichen Nutzen der Liste zweifelhaft erscheinen lässt, denn für diese Einträge wird der Hostname dann doch in seine eigentlich Adresse aufgelöst und die Verbindung hergestellt.

      Das stimmt nicht. Solange die hosts-Datei primär für DNS-Resolv genutzt wird werden diese Adressen zu 127.0.0.1/localhost umgesetzt.
      Kannst du testen mit z.B.

      [root@ws01 ~]# dig zzzzzz.petrodollar.org && ping -c 2 zzzzzz.petrodollar.org
      ...
      ;; ANSWER SECTION:
      zzzzzz.petrodollar.org.	3213	IN	A	103.224.182.253
      ...
      PING zzzzzz.petrodollar.org (103.224.182.253) 56(84) Bytes an Daten.
      64 Bytes von lb-182-253.above.com (103.224.182.253): icmp_seq=1 ttl=55 Zeit=165 ms
      64 Bytes von lb-182-253.above.com (103.224.182.253): icmp_seq=2 ttl=55 Zeit=165 ms
      
      [root@ws01 ~]# echo "0.0.0.0 zzzzzz.petrodollar.org" >> /etc/hosts
      
      [root@ws01 ~]# dig zzzzzz.petrodollar.org && ping -c 2 zzzzzz.petrodollar.org
      ...
      ;; ANSWER SECTION:
      zzzzzz.petrodollar.org.	3111	IN	A	103.224.182.253
      ...
      PING zzzzzz.petrodollar.org (127.0.0.1) 56(84) Bytes an Daten.
      64 Bytes von localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 Zeit=0.012 ms
      64 Bytes von localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 Zeit=0.023 ms
      
      [ich@ws01 ~]$ wget zzzzzz.petrodollar.org
      --2024-01-07 09:38:39--  http://zzzzzz.petrodollar.org/
      Auflösen des Hostnamens zzzzzz.petrodollar.org (zzzzzz.petrodollar.org)… 0.0.0.0
      Verbindungsaufbau zu zzzzzz.petrodollar.org (zzzzzz.petrodollar.org)|0.0.0.0|:80 … fehlgeschlagen: Verbindungsaufbau abgelehnt.

      Besser wäre so eine hosts-(Block)-Liste natürlich auf dem lokalen Router/DNS-Server aufgehoben.

      • Martin-MS hat auf diesen Beitrag geantwortet.

        GerBra Das stimmt nicht. Solange die hosts-Datei primär für DNS-Resolv genutzt wird werden diese Adressen zu 127.0.0.1/localhost umgesetzt.

        …solange der Hostname keine Unterstriche enthält und nicht systemd als Resolver verwendet wird. Wenn hosts z. B. so aussieht

        [root@archlinux ~]# cat /etc/hosts
        # Static table lookup for hostnames.
        # See hosts(5) for details.
        
        0.0.0.0 1.03rid7_easycoops.filter.clickbank.net
        0.0.0.0 google.de

        dann gehen sowohl ping als auch wget für das erst Ziel durch und für das zweite Ziel nicht:

        [root@archlinux ~]# ping -c1 google.de
        ping: google.de: Zu diesem Hostnamen gehört keine Adresse
        [root@archlinux ~]# ping -c1 1.03rid7_easycoops.filter.clickbank.net
        PING clickbank-apache-54377296.us-west-2.elb.amazonaws.com (35.167.122.11) 56(84) Bytes an Daten.
        ^C
        --- clickbank-apache-54377296.us-west-2.elb.amazonaws.com ping-Statistik ---
        1 Pakete übertragen, 0 empfangen, 100% packet loss, time 0ms
        
        [root@archlinux ~]# wget google.de
        --2024-01-07 10:59:02--  http://google.de/
        Auflösen des Hostnamens google.de (google.de)… fehlgeschlagen: Zu diesem Hostnamen gehört keine Adresse.
        wget: Host-Adresse »google.de« kann nicht aufgelöst werden
        [root@archlinux ~]# wget 1.03rid7_easycoops.filter.clickbank.net
        --2024-01-07 10:59:15--  http://1.03rid7_easycoops.filter.clickbank.net/
        Auflösen des Hostnamens 1.03rid7_easycoops.filter.clickbank.net (1.03rid7_easycoops.filter.clickbank.net)… 35.167.122.11, 54.191.88.1
        Verbindungsaufbau zu 1.03rid7_easycoops.filter.clickbank.net (1.03rid7_easycoops.filter.clickbank.net)|35.167.122.11|:80 … verbunden.
        HTTP-Anforderung gesendet, auf Antwort wird gewartet … 400 400
        2024-01-07 10:59:16 FEHLER 400: 400.

        und das journal meldet (abweichender Zeitstempel wegen früherem Versuch)

        Jan 07 10:46:47 archlinux systemd-resolved[269]: /etc/hosts:4: hostname "1.03rid7_easycoops.filter.clickbank.net" is not valid, ignoring.
        Jan 07 10:46:47 archlinux systemd-resolved[269]: /etc/hosts:4: line is missing any valid hostnames

        GerBra Besser wäre so eine hosts-(Block)-Liste natürlich auf dem lokalen Router/DNS-Server aufgehoben.

        Fände ich auch, weil man damit das gesamte Netzwerk und nicht nur ein Gerät schützen würde. Mir ist aber aus dem SoHo-Bereich kein Router bekannt, der >600.000 Ziele in einer Sperrliste verwalten könnte. Die Liste ließe sich aber auch deutlich ausdünnen, wenn man die Sperren z.B. auf die ganze Domain clickbank.net beschränken und nicht jeden einzelnen Host aufführen würde.

        • GerBra hat auf diesen Beitrag geantwortet.

          Martin-MS …solange der Hostname keine Unterstriche enthält und nicht systemd als Resolver verwendet wird.

          Ups. Da hält sich der systemd-resolved wohl strikt an RFC 952, obwohl die "reale" Welt anders aussieht. Mit dem glibc-resolver gibt es das Problem nicht.
          Ich habe auf die Schnelle auch nichts in den manpages gesehen daß man systemd-resolver entsprechend konfigurieren könnte.

          Martin-MS Mir ist aber aus dem SoHo-Bereich kein Router bekannt, der >600.000 Ziele in einer Sperrliste verwalten könnte.

          dnsmasq kann es wohl, ist halt kein Hardware-Blob:

          It is possible to use dnsmasq to block Web advertising  by  using  a  list  of  known  banner-ad servers,
          all  resolving to 127.0.0.1 or 0.0.0.0, in /etc/hosts or an additional hosts file. The list can be very long,
          dnsmasq has been tested successfully with one million  names.  That  size file needs a 1GHz processor and
          about 60Mb of RAM.

          Martin-MS Die Liste ließe sich aber auch deutlich ausdünnen

          OnTopic: Wäre ja eine kleine "Hausaufgabe" so ein Parser-Skript zu schreiben... <g>

            GerBra OnTopic: Wäre ja eine kleine "Hausaufgabe" so ein Parser-Skript zu schreiben... <g>

            Ähm... also ich würde da lieber etwas anderes schreiben wollen.

            Habe herausgefunden, dass "ublock Origin" (eine Firefox Erweiterung) deutlich mehr Werbeinhalte blockiert als eine "/etc/hosts" (habe mittlerweile diverse getestet). Ich nutze diese Seite für Wettervorhersagen: https://kachelmannwetter.com/de/wetter/2950159-berlin

            Hier werden die Werbeinhalte nicht von der "/etc/hosts" blockiert, weil die url's der Werbebanner auf dem Server von https://kachelmannwetter.com liegen, also wird die Werbung angezeigt. Die FF Erweiterung filtert das alles raus, auch bei anderen Seiten wie Stern oder Spiegel usw. Der Erste Aufruf einer Webseite dauert zwar etwas länger, aber dafür ist man zuverlässig die Werbung los. Weitere Aufrufe der Seite sind dann deutlich schneller.

            OnTopic:
            Ich überlege ein "Ausgabe-Skript" zu schreiben, dass es mir ermöglicht, jede Ausgabe eines Befehl- /Skriptaufrufs in der Konsole zu zeigen und parallel in eine *.log Datei zu schreiben. Man bräuchte dann nur das "Ausgabe-Skript" an einen Befehl oder Skriptaufruf anhängen.

            Bisher habe ich dafür jedes mal ein >> ${out} oder ein &>> $out geschrieben. Das funktioniert auch, aber wenn die Ausgabe umgeleitet ist, wird leider in der Konsole nichts angezeigt. Schöner wäre es, die Ausgabe in der Konsole zu sehen und bei Bedarf, eine *.log zu haben, in der man später in Ruhe etwas nachlesen kann.

            Da es die "log Funktion" und vor allem "Journald" bereits gibt, werde ich erstmal die manpages dazu lesen und versuchen zu verstehen.

            • Martin-MS hat auf diesen Beitrag geantwortet.

              fdell ch überlege ein "Ausgabe-Skript" zu schreiben, dass es mir ermöglicht, jede Ausgabe eines Befehl- /Skriptaufrufs in der Konsole zu zeigen und parallel in eine *.log Datei zu schreiben.

              Das kann tee

              • fdell hat auf diesen Beitrag geantwortet.

                Martin-MS Danke, sowas habe ich gesucht.
                Das funktioniert bei Aufrufen wiedf | tee ~/test.log

                Aber bei:
                wget -O hosts https://someonewhocares.org/hosts/zero/ | tee test.log
                Bleibt die "test.log" leer, Konsolenausgabe und Download erfolgen jedoch.

                • Martin-MS hat auf diesen Beitrag geantwortet.

                  fdell Aber bei:
                  wget -O hosts https://someonewhocares.org/hosts/zero/ | tee test.log
                  Bleibt die "test.log" leer, Konsolenausgabe und Download erfolgen jedoch.

                  tee lenkt nur die Standardausgaben um, die Ausgaben von wget werden aber auf dem Fehlerkanal ausgegeben. Den muss man also vorher auf die Standardausgabe umbiegen, versuche mal
                  wget -O hosts https://someonewhocares.org/hosts/zero/ 2>&1 | tee test.log

                  • fdell hat auf diesen Beitrag geantwortet.
                    7 Tage später

                    Hallo zusammen,

                    ich habe Fragen zur Verwendung von "grep" in einem Skript. In einer Textdatei (>4000 Zeilen) mit dem Muster (zeilenweise) "Vorname.Nachname" möchte ich suchen ob ein Ausdruck "foo" vorhanden ist.
                    Es handelt sich immer um die exakt selbe /Pfad/Textdatei. Dazu habe ich folgendes Skript geschrieben:

                    #!/bin/sh
                    user=$(getent passwd 1000 | cut -d':' -f1)
                    _file=$"/home/$user/temp/1.txt"
                    _name=$"_name"
                    
                    clear
                    echo "Bitte Name eingeben: "
                    read $_name
                    grep -i -n --color=auto $_name $_file

                    Das funktioniert auch. Ich würde gerne die Abfrage:

                    echo "Bitte Name eingeben: "
                    read $_name

                    Einsparen und stattdessen den Suchausdruck direkt an "grep" in der Form übergeben:
                    Skriptaufruf Suchausdruck
                    Ich möchte diese Suche als "bash_alias" nutzen, kann mir jemand weiterhelfen?

                    Was du suchst sind Parameter für dein Skript.

                    Du könntest $_name mit dem übergebenen Parameter belegen/ersetzen.
                    Siehe u.a.:
                    https://openbook.rheinwerk-verlag.de/shell_programmierung/shell_005_001.htm

                    Ich packe eine mögliche Variante mal in einen Spoiler, falls du es selbst rauskriegen wolltest.

                     #!/bin/sh
                     user=$(getent passwd 1000 | cut -d':' -f1)
                     _file=$"/home/$user/temp/1.txt"
                     _name=$"_name"
                     
                     if [[ "x$1" == "x" ]]; then
                        echo "Kein Suchbegriff eingegeben! Breche ab..."
                        exit 1
                     fi
                     
                     clear
                     _name="$1"
                     grep -i -n --color=auto "$_name" $_file
                     
                     # oder ohne _name verwenden zu muessen
                     # grep -i -n --color=auto "$1" $_file
                     #
                     # Aufruf dann mit:
                     # scriptname suchbegriff
                     # ohne Suchbegriff bricht das Skript ab (if-Schleife)
                     # Das funktioniert dann auch wenn es in einem Alias ist.
                    • fdell hat auf diesen Beitrag geantwortet.

                      GerBra Danke Dir. Diese Positionsparameter sind hilfreich, das muss ich genauer lesen.