Lokale Shell-Befehle einbinden

„ls -la“ kennt Ihr vermutlich aus jedem Konsolen-Tutorial für Linux. Aber habt Ihr auch schon mal einen lokalen Befehl nur für Euch gebaut ?

Globale oder Lokale Befehle ?

Globale Befehle kennt vermutlich jeder Linuxuser, denn alles was in /bin/ als Programm abgelegt und für alle Benutzer ausführbar ist, kann aufgerufen werden. Meistens laufen diese Programme im Context des aufrufenden Benutzers. Ausnahmen gibt es nur, wenn das SETUID-Flag gesetzt ist, dann darf jemand einen Befehl als ein bestimmter User ausführen. Üblicherweise ist das Root, aber andere user sind auch denkbar. „ls“, „find“, „uname“ usw. sind solche Befehle. So weit, so normal.

Wer den Videobeitrag Wie starten sich eigentlich Programme? gesehen hat, der ist da jetzt schon weiter, denn dort wird das genau erklärt. Kann ich Euch nur empfehlen, weil damit ist das hier möglich :

[marius@eve ~]$ firefox
Ich bin aber nicht der FireFox!
insgesamt 20
drwxrwxr-x. 2 marius marius 4096 14. Jul 09:45 .
drwxr-xr-x. 5 marius marius 4096 5. Jul 23:48 ..
-rwx——. 1 marius marius 100 14. Jul 09:45 firefox
-rwx——. 1 marius marius 112 5. Jul 23:48 fixrom
#!/bin/bash

echo „Ich bin aber nicht der FireFox!“

ls -la ~/.local/bin/
cat ~/.local/bin/firefox

[marius@eve ~]$

„Nicht die Mama“

Ok, Firefox ist jetzt nicht mehr Firefox .. super.. Browser kaputt gemacht 🙁 Was wäre, wenn im System ein Firefox Quantum installiert ist, der User aber Quantum ******** findet und lieber noch FF 52 ESR nutzen will? Egal welches Programm Firefox für seine Webseitendarstellung aufruft, es wird immer der systemweit installierte Firefox genommen. Der kleine Trick hier könnte das auf den Firefox ESR umleiten. Das wäre nur lokal für diesen Benutzer der Fall.

Wesentlich praktischer ist das andere kleine Programm in dem .local/bin Verzeichnis: fixrom . Wer den Beitrag über das fehlerhafte Fehlerfenster bei Runes of Magic gelesen hat, der weiß was es tut: Es verschiebt ein Fenster, daß nutzlos im Weg ist und dazu noch so defekt, daß man das nicht per Maus machen kann.

Da ich das kleine Script in das Lokale Bin-Verzeichnis verschoben habe, kann ich es von überall aus aufrufen und muß nicht mal den Pfad kennen, wo es wirklich liegt. ALT+F2 und die Eingabe von „fixrom“ startet es genauso, also wenn ich es in der Konsole eingebe. Ich kann es auch pauschal in die Desktopicons einbauen:

[marius@eve ~]$ cat Schreibtisch/Runes\ of\ Magic.desktop | grep Exec
Exec=env WINEPREFIX=“/home/marius/.wine“ wine C:\\\\windows\\\\command\\\\start.exe /Unix „/home/marius/Programme/GameforgeLive/Games/DEU_deu/Runes Of Magic/Runes of Magic.exe“

Dann würde es direkt nach dem Start von Runes of Magic gestartet werden und mir das Fenster sofort vom Hals halten. Aber, dann würde es auch bei jedem Start laufen und es muß nur eine Instanz davon aktiv sein, daher starte ich das von Hand. Gut, ich könnte das Script auch mit einem PID File versehen und prüfen ob es schon läuft und dann den Start umgehen, zeige ich vielleicht sogar mal 🙂

A Truth about Red Hat

Der vollständigkeithalber muß ich erwähnen, daß das mit dem Firefoxersatz unter Fedora nur klappt, wenn man seinen Pfad korrigiert. Wer nicht weiß was ein Pfad ist, schaut sich bitte das Video an. So sieht der Pfad unter Fedora aus:

$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/usr/sbin:/usr/sbin:/home/marius/.local/bin:/home/marius/bin:/usr/sbin/:/usr/sbin

So müßte er aussehen:

[marius@eve ~]$ echo $PATH
/home/marius/.local/bin:/home/marius/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/usr/sbin:/usr/sbin:/usr/sbin/:/usr/sbin

macht man übrigens so :

[marius@eve ~]$ export PATH=/home/marius/.local/bin:/home/marius/bin:$PATH

Natürlich müßt Ihr meinen Usernamen in Euren Änderungen durch Euren Namen ersetzen 😉

Wieso Fedora/Red Hat den Pfad so unbrauchbar gemacht haben, ist mir ein Rätsel, denn genau für solche Spielereien sind die lokalen Bin-Verzeichnisse da. Jetzt könnte man argumentieren, daß ein Angreifer damit den (im Beispiel) Firefox lokal ersetzen könnte und so ggf. noch mehr Schaden beim User durch Spionage anrichten kann. Das wäre zwar richtig, aber jeder, der von Remote da was hinlegen kann, kann noch ganz andere Dinge und hätte das Angriffsszenario nicht nötig 😉

Solange man aber nicht vor hat, ein Systemprogramm zu ersetzen, ist der Pfad eigentlich egal, nur .local/bin/ müßte halt drin vorkommen.

kleiner Spaß mit HowToForge

How To Forge .. kennt Ihr bestimmt. Ist so eine Webseite, wo Leute anderen Leuten zeigen, wie Dinge funktionieren. I.d.R. sind das spannende Sachen, wie man Webserver aufsetzt z.B.  . Es gibt aber auch Dinge, die nur eine Zeile lang sind, so wie der Artikel hier:  https://www.howtoforge.com/clear-bash-history/

Um was geht es überhaupt

„Das Löschen des BASH Kommandoarchives.“

Jeder der schon mal eine Bash-Shellkonsole benutzt hat, dürfte über die Bash-History gestolpert sein, als er ab- und unabsichtlich die Cursorsteuertasten benutzt hat. Damit kann man den vorherigen Befehl  nochmal sichtbar machen, Fehler beheben und wieder abschicken. Spart eine ganze Menge Tipparbeit.

Das lief dann auf … hinaus

Der Artikel lief dann auf diesen Einzeiler hinaus:

cat /dev/null > ~/.bash_history && history -c && exit

Und so schlicht das auch aussieht, da steckt doch glatt ein „Schönheitsfehler“ drin. Naja, ok, Fehler ist zu viel gesagt, ich würde es anders machen :

echo „“ > ~/.bash_history && history -c && exit

Bevor sich jemand zu Kommentarflames genötigt sieht, die eh gelöscht werden, was jetzt kommt ist rein akademisch.

Warum ?

Wir wollen die Datei leer haben, aber in einem definierten Zustand. Das Spezial-Device /dev/null erzeugt .. nichts.. Das ist aber weniger als „leer“ 🙂 Der Ansatz mit /dev/null funktioniert natürlich, weil cat solange was ausgibt, bis nichts mehr kommt und das passiert natürlich sofort. Also steht am Ende nichts mehr in der Datei, weil mit „>“ alles übergenagelt wird, was schon drin war.

Ich persönlich, finde ‚echo „“ >‘ als Konstrukt schöner, weil eindeutiger formuliert.

echo „“ zeigt deutlich, daß wir keinen Inhalt haben wollen. Bei /dev/null ergibt sich das nur indirekt aus dem Verhalten von cat und dem Verhalten von /dev/null . Beides muß man kennen um es zu verstehen. echo „“ sagt auch einem unbedarften Leser, daß es hier um „keinen Inhalt“ geht.

Wem das jetzt zu pingelig war, hat wohl noch nie versucht fremden Programmcode zu entziffern. Da spielt die eindeutige Benennung der Methode/Funktion eine wichtige Rolle, wenn der Code schon nicht Kommentiert ist. Das gleiche Prinzip gilt auch für Bashbefehle.

Soweit zu Teil 1..  jetzt reduzieren wir das mal brutalst auf 2 Befehle 🙂

echo „“ > ~/.bash_history; killall -9 bash

Was passiert hier ?

Zunächst mal machen wir die History platt, genau wie vorher. Jetzt killen wir alle Bash Shells die laufen, was in der Regel nur die eine sein wird. Shells von Root und anderen Benutzern können wir so nicht beenden, außer wir sind root. Da die Bash hart beendet wird, kann sie Ihre History nicht mehr auf Platte schreiben, womit die Datei auch nach dem Logout noch leer ist, welcher implizit beim Killen der Bashshell passiert. Ziel erreicht, ein Befehl weniger 😀

Zu Ursachen und Nebenwirkungen, fragen Sie Ihren Arzt und Drogendealer

Keine Frage, die Methode kann Kollateralschäden in anderen Bashsessions des Users verursachen. Sie ist auch um keinen Deut „besser“ als die ursprünglich vorgestellte Methode, nur kürzer. Und nur darum ging es heute.

Quelle: https://www.howtoforge.com/clear-bash-history/

How To Linux – Backspace funktioniert nicht ?

Du hast eine Linux CHROOT eingerichtet und die Backspace-Taste funktioniert nicht ?

Anstatt nach links, rückt die nach rechts ?

Du hast /etc/ komplett in die Chroot kopiert, aber es hilft nicht ?

stty -a gibt in der Chroot genau das gleiche aus, wie in der realen Umgebung ? (wenn nicht => stty sane )

Dann solltest Du mal das machen :

cd /
tar c /usr/share/terminfo | tar x -C /opt/chroot/

(den Pfad muß man natürlich an seine Installation anpassen)

 

 

Tip des Tages: Öfters mal Logfiles rotieren

Tomcat Logfiles können lang werden, daher sollte man diese desöftern rotieren.

Ganz unproblematisch ist das beim Tomcat aber nicht, denn im Gegensatz zu PHP Webanwendungen, stehen hier die Sessioninfos im RAM und nicht auf der Platte. Das hat beim Tomcat einen enormen Vorteil, weil der Server deutlich schneller an Infos kommt, als es z.B. PHP kann.

Der Nachteil liegt auf der Hand:  ein Neustart zerstört auch immer die Sessioninformationen. Gerade bei Shops ist das ein Problem. Hier muß die Sessionverwaltung dann auf Datenbanken ausgelagert werden, was bei verteilten Webanwendungen ohnehin gemacht werden muß.

Wo würde man daher das Logrotate ansetzen ?

Wer Serverdienste einsetzt, der braucht auch immer ein Startscript. Tomcat kommt zwar mit seinem eigenen startup.sh daher, aber auf ein klassisches Startscript ala init.d kann man eigentlich nicht verzichten. Hier ein Ausschnitt:

export CATALINA_HOME=/java/tomcat

ulimit -v unlimited -d unlimited -s unlimited -n 20000

PATH=$PATH:/usr/local/bin/

# See how we were called.
case "$1" in
 start)
 echo -n "Starting tomcat : "
 daemon /java/tomcat/bin/startup.sh
 RETVAL=$?
 echo
 ;;
 stop)
 echo -n "Stopping tomcat : "
 killtomcat
 RETVAL=$?
 echo
 ;;
 status)
 status tomcat
 RETVAL=$?
 ;;
 restart)
 $0 stop
 $0 start
 RETVAL=$?
 ;;
 *)
 echo "Usage: tomcat {start|stop|status|restart}"
 exit 1
esac

exit $RETVAL

und genau hier setzen wir an :

# See how we were called.
case "$1" in
 start)
 echo -n "Rotating Logs : "
 cd /usr/java/apache-tomcat/logs/
 echo "Deleting old files : "
 find . -ctime +100 -name "catalina.out*" -exec rm -fv {} \;
 COUNTER=0
 while [ $COUNTER -lt 99 ]; do
       echo The counter is $COUNTER
       let COUNTER=COUNTER+1
       if [ ! -f "catalina.out.$COUNTER" ]; then
           FILENAME="catalina.out.$COUNTER";
           break;
       fi
 done
 echo "Benutze $FILENAME";
 mv catalina.out $FILENAME
 echo "Compressing Logfile : $FILENAME"
 bzip2 -9 $FILENAME
 echo -n "Starting tomcat : "
 daemon /java/tomcat/bin/startup.sh
 RETVAL=$?
 echo
 ;;

Dieses Script ist natürlich nur ein Beispiel. Ihr müßt es noch anpassen an Eure Pfade und Präferenzen. Es wird Logfiles löschen, die älter als 100 Tage sind und maximal bis .99 zählen. Das kann je nach Häufigkeit des Starts Eures Tomcats dann eventuell nicht passen. Da müßt Ihr jetzt Eure Erfahrungen für Eurer System berücksichtigen.

Bitte beachtet, daß BZIP2 ein echter Zeitfresser ist, besonders in der Kombination mit 8 GB Logfile und -9 Option. Das packt hier auf einem nicht langsamen Server bereits seit 50 MInuten 😉 Das Ergebnis ist allerdings genial:

catalina.out.5: 53.987:1, 0.148 bits/byte, 98.15% saved, 8.250.838.531 in, 152.828.685 out.

Unter 2 % sind vom Logfile übrig geblieben 🙂

Wer jetzt meint, daß dieser Beitrag den 50 Minuten geschuldet ist, hat recht 😀 War leider ein echter Blocker.

 

Wie man in Bash Strings partiell vergleicht

Bash Stringvergleiche sind einfach :

if [ "$a" == "$b" ]; then 
          echo "gleich"
fi

Aber manchmal will man ja was auch nur Teilmengen vergleichen. Dazu braucht man die Doppelklammer und die Wildcards:

if [[ "$CERTNAME" == *"$HOSTNAME"* ]]; then
        echo "Teilvergleich erfolgreich"
fi

Wenn also HOSTNAME ein Teil von CERTNAME ist, dann trifft das obige zu. Wenn man == durch != ersetzt, kann man das Gegenteil abfragen. Es gibt aber noch einen anderen Weg, über RegExpressions:

if [[ "$CERTNAME" =~ .*$HOSTNAME.* ]]; then
   echo "RegExp ist gültig"
fi

Das hat den Vorteil, daß es auch etwas komplizierteres sein darf:

if [[ "$A" =~ .*(ab|vom).* ]]; then

Viel Spaß damit.

Cinnamondesktop entfernen, entfernt die falschen Pakete

Vor ein paar Tagen habe ich ja den Cinnamondesktop auf Fedora+Gnome nachinstalliert, und wollte das nun wieder entfernen. Leider entfernt „dnf erase @Cinnamon-Desktop“ einige wichtige Programme, die mit Gnome installiert wurden. Das führt natürlich zu dem Problem, daß man genau diese Pakete wieder installieren muß und dazu eine Liste braucht.

Wie macht man das ?

Abgleichen natürlich. Zunächst brauchen wir die Liste mit den RPMS, die installiert wurden:

grep -i -E „^Jul 01.*fc23“ /var/log/dnf.log-20160704  | grep install | awk ‚{print $7;}‘ | sort >/root/liste.install

Dazu muß man natürlich wissen, wann man Cinnamon installiert hat, in meinem Fall am „Jul 01“ .

Daran denken: An dem Tag können noch andere Pakete installiert worden sein, also ggf. den Grep um die Uhrzeit erweitern!

Jetzt brauchen wir noch die gleiche Liste für die entfernten Pakete:

grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘ | sort >/root/liste.erased

Wie bei den Installdaten, könnten auch hier noch andere Pakete deinstalliert worden sein, also auch hier ggf. die Uhrzeit einbauen!

Wer nachvollziehen will, was die einzelnen Befehle machen, kann Sie auch einzeln aufrufen :

grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘ | sort
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log

Nun hat man zwei Listen mit Paketen. Alle die Pakete, die nicht in der Install-Liste sind, aber in der Erased-Liste, müssen wieder auf den Rechner drauf.

Jetzt könnte es soooo einfach sein :

grep -vf /root/liste.install /root/liste.erased

Ist es aber nicht, denn die Listen passen nicht zusammen. Wir müssen die Paketnamen erst normieren:

sed -e „s/\.x86_64//“ /root/liste.install > /root/liste.install2

sed -e „s/\.fc23.*//“ -e „s/:.*$//“ -e „s/-[0-9].*//“ /root/liste.erased  > /root/liste.erased2

Jetzt können wir Sie vergleichen :

grep -vf /root/liste.install2 /root/liste.erased2

Das zeigt alle Tools an, die in der Install-Liste fehlen, also zuviel deinstalliert wurden.

Das sollte man jetzt von Hand nochmal aussortieren, aber zur Not ginge auch:

grep -vf /root/liste.install2 /root/liste.erased2 | awk ‚{print „dnf -y install „$1;}‘ | bash

und alles würde automatisch installiert werden.

ACHTUNG: Hinweis für spätere Zeiten :

Als dieser Artikel geschrieben wurde, war Fedora 23 aktuell auf einem 64Bit System installiert. Wer andere Versionen einsetzt, muß die ganzen Anweisungen selber sinnvoll anpassen.

Bash: watch als Prozessüberwacher mißbrauchen

Oftmals hat man das Problem, daß Daemons unter Linux abstürzen und es keinen Masterprozess gibt, der sowas überwacht und neustartet.

Die Daemontools von DJB hatten da eigens so ein Überwachungsprogramm, aber im Prinzip ist so ein Tool nichts anders als eine Endlosschleife, die einfach nur den gestorbenen Prozess neustartet:

for(…) { run(„serverdaemon“); }

Anstatt jetzt jedesmal so ein Loopprogramm zuschreiben, wäre ja etwas universelles gut, oder ? 🙂

Einfach watch benutzen : watch -n 0,1 „… bashzeile zum starten…“

Das könnte dann so aussehen :

#!/bin/bash

watch -n 0,1 „/usr/bin/meinserverdaemon profile.one -s targetmode -p 887“

Leider kann man ja init.d und systemctl Starts nicht in eine Schleife legen, da diese Prozesse die eigentlich zu startenden Programme absplitten.

Zum Stoppen muß man nun allerdings erst das Watch und dann den Serverdaemon stoppen, sonst hat man mit Zitronen gehandelt.