Hallo David, hallo Leute, Am Sonntag, 10. Juli 2005 03:29 schrieb David Haller:
Am Sun, 10 Jul 2005, Christian Boltz schrieb:
-------------------------------------------------------------------- --- #!/bin/bash
# usercron.daily # # Copyright (C)2005 by Christian Boltz - www.cboltz.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version.
me="${0//.*\/}"
Das ist ein "bashism", auf SuSE Linux legitim, da sowas ja AFAIR sogar in den bootscripten verwendet wird. Ansonsten:
Klar, deshalb ja auch #!/bin/bash ;-) Die SuSE-Bootscripte verwenden auch teilweise bash-spezifische Dinge - allerdings steht trotzdem meistens #!/bin/sh drin :-(
me="`basename \"$0\"`" (und zwar so und nicht anders gequoted!)
Klar.
# get list of users userlist="`cut -d: -f1 /etc/passwd`"
# if /etc/cron.allow exists, allow only users in this file test -f /etc/cron.allow && userlist="`cat /etc/cron.allow`"
Wenn du (oben) schon Bashisms verwendest:
&& userlist="$(
Nett, kannte ich noch gar nicht.
for user in $userlist ; do
Besser:
getent passwd | cut -d':' -f1 | while read -r user; do
Stimmt eigentlich. Usernamen mit Leerzeichen sollten zwar "eigentlich"[tm] nicht vorkommen, aber man weiß ja nie ;-)
oder wenn die user alle auch in der passwd stehen:
cut -d':' -f1 /etc/passwd | while read -r user; do
Bzw. mit dem Test mit cron.allow:
==== PASSWD='/etc/passwd' ALLOW='/etc/cron.allow' # [..] if test -f "$ALLOW" && test -r "$ALLOW"; then listusers='cat "$ALLOW"' else # listusers='cat "$PASSWD"' listusers='getent passwd' fi
$listusers | cut -d ':' -f 1 | while read -r user; do ====
Schöne Lösung. Darf ich die übernehmen?
# deny cronjobs for users in /etc/cron.deny grep "^[ ]*$user[ ]*$" /etc/cron.deny &>/dev/null && continue # ^^^ und ^^^ = Space Tab
grep -q "^[[:space:]]*$user[[:space:]]*$" /etc/cron.deny && continue
Ist zumindest fürs Zitieren in Mails besser ;-)
# get homedir for $user homedir="`grep \"^$user:\" /etc/passwd | cut -d: -f6`";
Auch hier kann man 'getent' verwenden. "Einfacher" (naja, eher "effektiver" ;) ist aber:
homedir="`awk -F ':' -v u=\"$user\" '$1 == u { print $6; }' /etc/passwd`";
bzw.:
homedir="`getent passwd | awk -F ':' -v u=\"$user\" '$1 == u { print $6; }'`";
Wenn schon awk, dann mit obiger Konstruktion mit $listusers - auch wenn das im Fall von /etc/cron.allow einen useless use of cat gibt ;-)
Achso: da das script unter cron laufen soll, sollte wohl noch
a) PATH zum script-Anfang ergaenzen / explizit setzen, oder b) alle Programme explizit mit Pfad aufrufen.
Eher a) ;-)
Dazu also "suchen&ersetzen" von cat, cut, grep, awk, usw.... Naja, eigentlich sollten alle verwendeten Programme in /bin oder /usr/bin/ liegen, und die beiden Verzeichnisse sind in PATH eines cron-scriptes... Zumindest unter SuSE bzw. wohl auch den meisten (allen?) anderen GNU/Linux Systemen...
Ich hoffe doch.
# test for .cron.* in homedir test -d "$homedir/$dirname" || continue
# search and execute scripts in ~/cron.* ls -1 "$homedir/$dirname/" | while read file ; do
Das '-1' ist ueberfluessig, schadet aber auch nicht. ls schreibt grundsaetzlich nur einspaltig, wenn stdout kein Terminal ist (sondern z.B. eine pipe). Das aber nur nebenbei ;)
test -x "$homedir/$dirname/$file" && {
Ich verwende, wenn ich Variablen zusammenfuege meistens ${} um auf der sicheren Seite zu sein, also 'test -x "${homedir}/${dirname}/${file}"' Sollte aber natuerlich auch so funktionieren ;)
Durch den / als einziges Zwischenzeichen habe ich keine Bedenken. Ansonsten ist Dein Einwand korrekt und bei mir auch nicht unüblich.
# log and execute logger -t "$me" "($user) CMD ($homedir/$dirname/$file)" su "$user" -c "$homedir/$dirname/$file" } done done -------------------------------------------------------------------- ---
Die Benutzer können in ~/.cron.daily usw. Scripte anlegen, die dann mit entsprechenden User-Rechten ausgeführt werden.
Gute Idee jedenfalls ;)
Achtung: Obiges Script habe ich eben in Rekordzeit getippt - es ist also nur minimal getestet. Die Behandlung von cron.deny und cron.allow [1] habe ich eingebaut, aber nicht getestet.
Sieht ok aus, wenn in den beiden Datein jeweils einfach eine (zeilenweise) Liste von Usernamen steht.
Hatte ich auch vermutet, aber mangels schriftlichem Beweis...
Falls jemand Bugs oder mögliche Sicherheitslücken auffallen - bitte melden!
s.o. Eigentlich nicht. Sieht auch so sehr gut aus, ist anstaendig gequoted (wichtig!) usw. Aber ich musste halt trotzdem mal wieder meinen Senf dazu geben ;) Deine Version sieht jedenfalls schon "sauber" aus.
Danke ;-)
Eine noch offene Baustelle ist der Mailversand im Fehlerfall - die Mail geht nämlich grundsätzlich an root, nicht an den jeweiligen User. Falls jemand eine gute Idee hat, wie man dieses Problem elegant löst - immer her damit ;-) [2]
Einfachst Variante, nur mit stderr als Mail:
su "$user" -c "$homedir/$dirname/$file" 2>&1 >/dev/null | mail "$user"
Man achte auf die Reihenfolge von '2>&1' und '>/dev/null'...
Das Problem dabei: Wenn es keine Ausgabe gibt, erhält der User eine leere Mail - das will ich eigentlich vermeiden.
Oder willst du evtl. Fehlermeldungen des scripts selber auch dem User zukommen lassen?
Nö, das ist wieder eine Sache für root ;-) Gruß Christian Boltz -- "Wirklich praxisnah wären Münzen zu EUR 0,99." [Wolfgang Schwanke in de.etc.sprache.deutsch]