Hallo,
ich bin mir sicher, erst vor kurzem in der Liste etwas zu meinem
Problem gelesen zu haben. Aber in welchem Zusammenhang und wo weiss ich
einfach nicht mehr :-(
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_
will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo
edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls
nicht geschafft.
Vermutlich ist es ja wieder sehr einfach, wenn man es weiss ;-)
Eine gute Nacht,
Heinz.
--
E-Mail: Heinz W. Pahlke
On Son, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote: [...]
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_ will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Hmm, sed arbeitet ja nur zeilenweise. Ich bin mir nicht sicher, ob
das damit zu klären ist. Aber wieso hängst Du nicht einfach die
Zeilen aneinander?
while read i; do
text="$text$i"
done
On 14-Jul-2001 Jan Trippler wrote:
On Son, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote:
will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Hmm, sed arbeitet ja nur zeilenweise. Ich bin mir nicht sicher, ob das damit zu klären ist. Aber wieso hängst Du nicht einfach die Zeilen aneinander?
while read i; do text="$text$i" done
Weil damit auch die Absaetze im Text verschwinden :-(
Vielleicht muss ich doch mal mein Vorhaben erklaeren. Standardmaessig
arbeite ich mit ApplixWord. Oft brauche ich spaeter aber nur noch den
Inhalt, aber nicht die Formatierung. Mit Applix in Ascii-Dateien zu
konvertieren ist mir aber etwas zu aufwendig. Also schreibe ich mir
gerade ein kleines Script.
Inzwischen entsprechen die Ergebnisse auch weitgehend meinen
Erwartungen, bis auf die bloeden Zeilenenden, die einfach nerven:
----------------------------8<------------------------------------
Das ist ein voelliger Nonsense-Text lediglich zur Demonstr
ation des Problems.
Das ist ein voelliger Nonsense-Text lediglich zur Demonstr
ation des Problems.
----------------------------8<------------------------------------
Dein Vorschlag macht daraus leider ein:
----------------------------8<------------------------------------
Das ist ein voelliger Nonsense-Text lediglich zur Demonstration des
Problems. Das ist ein voelliger Nonsense-Text lediglich zur
Demonstration des Problems.
----------------------------8<------------------------------------
Die Zeilen werden zusammengefasst, aber leider auch die Absaetze.
Vermutlich muss ich mir heute abend mal ein Buch zur Bash raussuchen.
Applix markiert die Zeilenenden naemlich mit einem \, waehrend die
Absaetze einfach wirklich als Absatz gespeichert werden. Also muesste
ich dein Script entsprechend um eine Abfrage erweitern, dass nur Zeilen
mit einem \ am Ende zusammengefasst werden.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
* Jan Trippler schrieb am 15.Jul.2001:
On Son, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote:
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_ will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Hmm, sed arbeitet ja nur zeilenweise. Ich bin mir nicht sicher, ob das damit zu klären ist. Aber wieso hängst Du nicht einfach die Zeilen aneinander?
Geht glaube ich auch mit sed, aber nicht einfach mit s/.../.../ sondern mit sed -n ... so, daß nicht jede Zeile ausgdruckt wird und dann mit p das was doch ausgedruckt werden soll, und irgendwas in irgendwelche Register. Aber das geht recht tief in sed hinein. Da nehme ich lieber perl. Bernd -- Bei Fragen an die Liste erst mal nachschauen, ob es diese Frage nicht schon einmal gegeben hat. Ein Archiv der Liste findest Du auf: http://lists.suse.com/archives/suse-linux |Zufallssignatur 7
On Son, 15 Jul 2001 at 01:24 (+0200), Jan Trippler" wrote: [...]
while read i; do text="$text$i" done
Ich habe die anderen Mails zum Thema leider schon weggeschmissen,
aber das Problem mit den Absätzen kannst Du (neben den
Perl-Vorschlägen) auch mit der Shell in den Griff kriegen:
while read i; do
if test -z "$i"; then
echo -e "$text\n"
text=
else
text="$text$i"
fi
done
Hallo Jan, danke, deine Shell-Loesung funktioniert. Anderes haette mich allerdings auch gewundert. Bloss - ich verstehe sie nicht, trotz man bash. On 15-Jul-2001 Jan Trippler wrote:
while read i; do
^ Es soll etwas eingelesen werden, klar, aber i?
if test -z "$i"; then
^^^^^^^ Die Variable i soll null sein, aber woher kommt sie (vom obigen i?) und warum?
echo -e "$text\n"
^^^^^^^^^^^^ Wenn die Zeile ein new-line enthaelt, dann...
text=
^^^^^ passiert nichts.
else
^^^^ andernfalls
text="$text$i"
^^^^^^^^^ fuege die Zeilen aneinander.
fi done
^ Hier wird erst gesagt, welche Datei eingelesen werden soll.
test -n "$text" && echo $text
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Wenn es ein Ergebnis gibt, soll es
ausgegeben werden.
Aber ich sehe ein, dass diese Liste nicht dazu da ist, mir die bash
beizubringen. Also muss ich wohl doch losziehen, mir mal ein
vernuenftiges Buch zur Shellprogrammierung zu kaufen. Das, was ich
habe, ist doch nicht so doll, und auf dem Bildschirm lese ich laengere
Texte nur sehr ungern.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
Hallo Heinz, On Sunday, 15. July 2001 22:45, Heinz W. Pahlke wrote:
Bloss - ich verstehe sie nicht, trotz man bash.
On 15-Jul-2001 Jan Trippler wrote:
while read i; do [...] done
die Variable "i" steht für die im jeweiligen Schleifendurchlauf eingelesene Zeile des Input-Files und könnte auch anders heißen. Wesentlich ist, dass die Schleife bei jedem Durchlauf eine Zeile einliest. Schöne Grüße, Stephan -- Stephan Hakuli | mailto: stephan@hakuli.de | * GnuPG/PGP-Key * | callto: 01 71 - 651 89 43 | available, please | surfto: http://www.hakuli.de | visit my homepage
Hallo Stephan, On 15-Jul-2001 Stephan Hakuli wrote:
die Variable "i" steht für die im jeweiligen Schleifendurchlauf eingelesene Zeile des Input-Files und könnte auch anders heißen. Wesentlich ist, dass die Schleife bei jedem Durchlauf eine Zeile einliest.
Jetzt wird mir bereits vieles klarer.
Besten Dank,
Heinz.
--
E-Mail: Heinz W. Pahlke
On Son, 15 Jul 2001 at 22:45 (+0200), Heinz W. Pahlke wrote:
danke, deine Shell-Loesung funktioniert. Anderes haette mich allerdings auch gewundert.
Jetzt hast du mich verlegen gemacht *rot werd und mit den Füßen scharr* ;-)
Bloss - ich verstehe sie nicht, trotz man bash.
Och, das kriegen wir schon hin.
Fangen wir oben an:
while read i; do
done
ist eine Schleife, die solange läuft, wie der read noch true
liefert. read liest von der Standardeingabe in eine Variable (die
ich i genannt habe. Man muss immer beachten, dass in der Shell bei
einer Variablen_zuweisung_ nie das $ vor den Variablen-Namen gesetzt
wird, nur dann, wenn der Variablen_inhalt_ abgefragt wird - wie z.
B. beim echo).
Ich tendiere bei kleinen Scripts zu kurzen Variablennamen (bei einer
Variablen namens Gruesse_an_meine_Magengeschwuere kriegt man
spätestens beim zweiten Tippen die Krätze ;-). Wenn es länger wird
und mehrere Variablen im Script auftauchen, sollten sie einen
sprechenden Namen kriegen.
Da bei einer Shell immer die Standard-I/O-Kanäle umgebogen werden
können, kann man also auch stdin statt vom Terminal aus einer Datei
lesen lassen. Also kann man den read aus einer Datei füttern, das
bewirkt die Eingabe-Umleitung:
while read i; do
done Aber ich sehe ein, dass diese Liste nicht dazu da ist, mir die bash
beizubringen. Also muss ich wohl doch losziehen, mir mal ein
vernuenftiges Buch zur Shellprogrammierung zu kaufen. Das, was ich
habe, ist doch nicht so doll, und auf dem Bildschirm lese ich laengere
Texte nur sehr ungern. Der Kofler ist recht gut und zum Probieren kann man sich immer die
rc-Scripts von SuSE nehmen. Da wird eigentlich eine ganze Menge von
dem, was die Bash kann, genutzt.
Die beste Methode zum Shell-Lernen ist IMHO immer noch das
Ausprobieren. Ich habe in meinem Home-Verzeichnis unter progs (da
liegen meine Projekte) ein tests-Verzeichnis, in das wandern so
Sachen wie das Teil oben. Dann schnappe ich mir irgendeine Datei aus
dem System und probiere rum.
Jan
On 16-Jul-2001 Jan Trippler wrote:
On Son, 15 Jul 2001 at 22:45 (+0200), Heinz W. Pahlke wrote:
Bloss - ich verstehe sie nicht, trotz man bash.
Och, das kriegen wir schon hin.
Vielen Dank fuer deine ausfuehrliche Erklaerung. Im einzelnen nehme ich
sie mir aber erst heute abend vor.
Und dann geht es daran, das Script so umzuschreiben, dass ich die
Dateien nicht erst immer umbenennen muss, um sie konvertieren zu
koennen. Schliesslich soll es nach dem Prinzip "Befehl datei.alt >
datei.neu" funktionieren.
Beste Gruesse,
Heinz.
PS: Auf das Bash-Buch verzichte ich natuerlich trotz deiner guten
Erklaerung nicht. Bloss heute schickt man seinen schlimmsten Feind
nicht raus, und eigentlich mag ich mich :-)
--
E-Mail: Heinz W. Pahlke
Hello Heinz, Monday, July 16, 2001, 9:15:13 AM, Heinz Pahlke wrote: Bei mit läuft seit geraumer Zeit dieses Script auf Dateien, die von Windose stammen und die ich unter UNIX in Oracle lade. sed 's/.$//' $1 > /tmp/$1.$$ mv /tmp/$1.$$ $1 "Legende": $1: Dateiname $$: Prozess ID des sed Jobs -- Best regards, Roland mailto:roland.suehsmuth@boecker-online.de
On Mon, 16 Jul 2001 at 10:03 (+0200), Roland Suehsmuth wrote:
Monday, July 16, 2001, 9:15:13 AM, Heinz Pahlke wrote:
Bei mit läuft seit geraumer Zeit dieses Script auf Dateien, die von Windose stammen und die ich unter UNIX in Oracle lade.
sed 's/.$//' $1 > /tmp/$1.$$ mv /tmp/$1.$$ $1
"Legende": $1: Dateiname $$: Prozess ID des sed Jobs ^^^^^^^^ nö, des Shell-Scripts.
Dieser sed macht aber nicht das, was Heinz wollte. Du entfernst damit das Win*-Zeilenende (CR-LF). Der Mechanismus, eine temp. Datei zu erzeugen, ist aber anwendbar. Jan
Hello Jan, Monday, July 16, 2001, 12:31:10 PM, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 10:03 (+0200), Roland Suehsmuth wrote:
sed 's/.$//' $1 > /tmp/$1.$$ mv /tmp/$1.$$ $1
"Legende": $1: Dateiname $$: Prozess ID des sed Jobs ^^^^^^^^ nö, des Shell-Scripts. ACK. Sorry und danke für's aufpassen. Dieser sed macht aber nicht das, was Heinz wollte. Du entfernst damit das Win*-Zeilenende (CR-LF). Ich hatte nur die erste Frage gelesen und danach hätte dies damit zu tun haben können. In den folgenden Mails wurde es dann klarer.
-- Best regards, Roland mailto:roland.suehsmuth@boecker-online.de
On Mon, 16 Jul 2001 at 09:15 (+0200), Heinz W. Pahlke wrote: [...]
Und dann geht es daran, das Script so umzuschreiben, dass ich die Dateien nicht erst immer umbenennen muss, um sie konvertieren zu koennen. Schliesslich soll es nach dem Prinzip "Befehl datei.alt > datei.neu" funktionieren.
Einfach den Mechanismus, wie ihn Roland gezeigt hat, abwandeln (ich habe gleich noch ein wenig Error-Handling eingebaut): ### Script ### #! /bin/bash # Aufruf: zende Dateiname # eigener Programmname prg=`basename $0` # Test, ob Dateiname uebergeben wurde if test -z "$1"; then echo "Aufruf: $prg Dateiname" >&2 exit 1 fi # Test ob Datei ex. und lesbar ist if test ! \( -f "$1" -a -r "$1" \); then echo "$prg: Datei \"$1\" existiert nicht oder nicht lesbar" >&2 exit 2 fi # temp. Datei tmp_datei=/tmp/datei.$$ # wenn vorhanden, loeschen; Fehler wenn dies nicht moeglich ist if test -e $tmp_datei; then if ! rm $tmp_datei 2>/dev/null; then echo "$prg: kann temp. Datei \"$tmp_datei\" nicht loeschen!" >&2 exit 3 fi fi # Schleife while read i; do if test -z "$i"; then echo -e "$text\n" >>$tmp_datei text= else text="$text$i" fi done <$1 test -n "$text" && echo $text >>$tmp_datei # Datei in Originaldatei umbenennen if ! mv $tmp_datei $1 2>/dev/null; then echo "$prg: Kann Datei \"$1\" nicht ueberschreiben" >&2 exit 4 fi exit 0 ### Scriptende ### Jan
On 16-Jul-2001 Jan Trippler wrote:
On Mon, 16 Jul 2001 at 09:15 (+0200), Heinz W. Pahlke wrote: [...]
Und dann geht es daran, das Script so umzuschreiben, dass ich die Dateien nicht erst immer umbenennen muss, um sie konvertieren zu koennen. Schliesslich soll es nach dem Prinzip "Befehl datei.alt > datei.neu" funktionieren.
Einfach den Mechanismus, wie ihn Roland gezeigt hat, abwandeln (ich
Klar schaue ich mir die Beispiele an (mein lokales Listenarchiv gibt da auch noch einiges zusaetzlich her), aber so zwischendurch schaffe ich es doch nicht. Mindestens ein Abend geht bei meinen Versuchen in der Regel doch drauf, weil ich eben oft nach dem Motto "try and error" vorgehe.
habe gleich noch ein wenig Error-Handling eingebaut):
### Script ###
Vielen Dank. Ist schon irre, wie Du und einige andere das scheinbar aus
dem Aermel schuetteln. Aber ich weiss schon, dass vor diesem Erfolg
viel Schweiss stand.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
Ich kann's mir mal wieder nicht verkneifen... On Mon, 16 Jul 2001, Jan Trippler wrote:
# eigener Programmname prg=`basename $0` [..] # temp. Datei tmp_datei=/tmp/datei.$$
Also, wenn wir schon $prg habe, dann waere schon ein: tmp_datei="/tmp/${prg}.$$" besser. Nochbesser ist aber, wenn auch AFAIK immer noch nicht sicher: tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1 zum testen in der Shell: user@host:~ $ ( mktemp /root/test.$$.XXXXXX || exit 1; ) Cannot create temp file /root/test.3061.FS2eER user@host:~ $ ( mktemp /tmp/test.$$.XXXXXX || exit 1; ) /tmp/test.3061.dGT8Dj user@host:~ $ die '()' drumherum sind dabei dazu, dass ne sub-shell geoeffnet wird (und nicht das terminal geschlossen wird). Interessant, ist dabei, dass $$ die PID der shell ist, wo das (mktemp) ein- gegeben wird und nicht die der subshell ;) -dnh -- Die ultimativen Man-Pages haben ein ".c" als Dateiendung. -- am DLUG-Stammtisch
Moin, On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
Ich kann's mir mal wieder nicht verkneifen...
Das habe ich schon langsam vermisst ;-)
On Mon, 16 Jul 2001, Jan Trippler wrote:
# eigener Programmname prg=`basename $0` [..] # temp. Datei tmp_datei=/tmp/datei.$$
Also, wenn wir schon $prg habe, dann waere schon ein:
tmp_datei="/tmp/${prg}.$$"
besser. Nochbesser ist aber, wenn auch AFAIK immer noch nicht sicher:
$prg kam hinterher dazu, als ich feststellte, dass die Fehlermeldungen schöner aussehen könnten. Du hast aber recht - der Name ist so (im Falle z. B. von Programmabbrüchen) besser zu identifizieren und die Gefahr einer Doppelnutzung ist geringer.
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Ja, noch schicker ;-) Aber vielleicht für ein "Zu Hause System mit einem Benutzer ohne allzuviel Dienste" mit Kanonen nach Spatzen geschossen? Bei mir ist in tmp nicht viel los - auch nicht auf meinem Server. Grundsätzlich ist mktemp natürlich vorzuziehen. Ich sollte mich eigentlich auch dazu zwingen, ihn konsequent einzusetzen. Jan
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
Ich kann's mir mal wieder nicht verkneifen...
Das habe ich schon langsam vermisst ;-)
Ach? *g* Kann ich das dann oefter machen?
On Mon, 16 Jul 2001, Jan Trippler wrote:
# eigener Programmname prg=`basename $0` [..] # temp. Datei tmp_datei=/tmp/datei.$$
Also, wenn wir schon $prg habe, dann waere schon ein:
tmp_datei="/tmp/${prg}.$$"
$prg kam hinterher dazu, als ich feststellte, dass die Fehlermeldungen schöner aussehen könnten. Du hast aber recht - der Name ist so (im Falle z. B. von Programmabbrüchen) besser zu identifizieren und die Gefahr einer Doppelnutzung ist geringer.
Ack. Naja, Hartkodieren kann man's auch ;)
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Ja, noch schicker ;-) Aber vielleicht für ein "Zu Hause System mit einem Benutzer ohne allzuviel Dienste" mit Kanonen nach Spatzen geschossen? Bei mir ist in tmp nicht viel los - auch nicht auf meinem Server. Grundsätzlich ist mktemp natürlich vorzuziehen. Ich sollte mich eigentlich auch dazu zwingen, ihn konsequent einzusetzen.
Naja, ich selbst gehe mal eher davon aus, dass ein ${prg}.$$
relativ sicher ist, denn dass eine PID mehrfach vergeben wird
waere eigenartig. ABER: Da muesste man dann eigenlich darauf
testen, ob die Datei schon existiert (von frueheren Aufrufen, die
PIDs beginnen ja nach defaultmaessig 32k wieder bei 2 (bzw. der
naechsten freien, was besonders bei laengeren Compilierorgien zu
beobachten ist ;))) und diese dann ggfs. loeschen oder sonstwas...
Insofern hat mktemp, selbst auf Einzeluser-Kiste wie's meine und
deine sind seine Berechtigung, denn da ist die Pruefung auf einen
Dateinamenskonflikt bereits "drin" :)
On Die, 17 Jul 2001 at 00:34 (+0200), David Haller wrote:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
Ich kann's mir mal wieder nicht verkneifen...
Das habe ich schon langsam vermisst ;-)
Ach? *g* Kann ich das dann oefter machen?
Na gut, wenn Du artig bleibst ;-) [...]
Naja, ich selbst gehe mal eher davon aus, dass ein ${prg}.$$ relativ sicher ist, denn dass eine PID mehrfach vergeben wird waere eigenartig. ABER: Da muesste man dann eigenlich darauf testen, ob die Datei schon existiert (von frueheren Aufrufen, die PIDs beginnen ja nach defaultmaessig 32k wieder bei 2 (bzw. der naechsten freien, was besonders bei laengeren Compilierorgien zu beobachten ist ;))) und diese dann ggfs. loeschen oder sonstwas...
Ist in meinem Script drin - sooo weit war ich dann doch schon *g*
Naja, ich muss zugeben, dass ich fast lieber noch ein "festes" Namens- schema fuer meine tmp-dateien nehme, z.B. /tmp/${prg}.$$.temp (und dann ein 'trap "rm $temp_file; exit 1" 1 2 3 6 7 13 15' mit einbaue... Je nach script durchaus aber auch einfach nur ein /tmp/${prg}.tmp (!!) das gnadenlos ueberschrieben/geleert/geloescht wird... Motto: Alles in /tmp darf jederzeit geloescht werden *eg*
Man kann das doch kombinieren (das Aufräumen per trap vergesse ich auch jedes 2. Mal :-(). Also per mktemp den temporären Dateinamen ermitteln und per trap diese Datei im Falle eines Abbruchs löschen. Das ist dann eigentlich schon ein ziemlich sauberer Weg. Den Rest an liegengebliebenen temp. Dateien erledigt dann der cron.daily (wenn in config.rc ordentlich konfiguriert). Dein Motto ist mir ein wenig zu rigoros ;-) Solange, wie ein Programm die Datei braucht, sollte sie schon in tmp existieren dürfen, und da sollte auch kein anderer Prozess mal einfach drüberlöschen dürfen. Jan
PS: Wo ist Wolfgang eigentlich?
Man sieht ihn gelegentlich noch in suse-security.
On Die, 17 Jul 2001, Jan Trippler wrote:
On Die, 17 Jul 2001 at 00:34 (+0200), David Haller wrote:
On Mon, 16 Jul 2001, Jan Trippler wrote: Ach? *g* Kann ich das dann oefter machen?
Na gut, wenn Du artig bleibst ;-)
OK :)
[...] Ist in meinem Script drin - sooo weit war ich dann doch schon *g*
Ja, hatte ich nicht vergessen...
Man kann das doch kombinieren (das Aufräumen per trap vergesse ich auch jedes 2. Mal :-(). Also per mktemp den temporären Dateinamen ermitteln und per trap diese Datei im Falle eines Abbruchs löschen.
GENAU! :)
PS: Wo ist Wolfgang eigentlich?
Man sieht ihn gelegentlich noch in suse-security.
Schade eigentlich.... -dnh -- Gibt es eigentlich in dag° "echten Blödsinn" ? Ich meine jetzt ausser meinem Bescheidenen Beiträgen dazu. [WoKo in dag°]
* David Haller schrieb am 17.Jul.2001:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Wenn es nicht funktioniert, dann sollte da aber schon eine Fehlermeldung kommen. Kommt doch sonst nie einer drauf, daß es an der Nichtanlegbarkeit (was für ein Wort ;)) der Tempdatei liegt. Das $$ ist hier eigentlich nicht mehr nötig. mktemp macht einen Einzigartigen Namen. Nur sowas wie ${prg} schriebe ich auch davor, denn dann hat man eine bessere Chance herauszubekommen, was das für eine Datei ist.
Naja, ich muss zugeben, dass ich fast lieber noch ein "festes" Namens- schema fuer meine tmp-dateien nehme, z.B. /tmp/${prg}.$$.temp (und dann ein 'trap "rm $temp_file; exit 1" 1 2 3 6 7 13 15' mit einbaue...
Was spricht gegen diese Zeile, wenn Du temp_file vorher wie oben definiert hast, also mit mktemp? Dann kanst Du es genauso in Deiner trap aufnehmen oder später sonstwie wegräumen.
Je nach script durchaus aber auch einfach nur ein /tmp/${prg}.tmp (!!) das gnadenlos ueberschrieben/geleert/geloescht wird... Motto: Alles in /tmp darf jederzeit geloescht werden *eg*
Damit sollte man rechnen. Ist ja auch eine Frage, was das Programm macht. Kann sein, daß es nicht so wichtig ist, dann ist es egal. Wenn es entscheident ist, dann muß man Vorsorge treffen, wenn die tempdatei nicht mehr da ist. Bernd -- ACK = ACKnowledge = Zustimmung | NAC = No ACknowledge = keine Zustimmung DAU = Dümmster Anzunehmender User | LOL = Laughing Out Loud = Lautes Lachen IIRC = If I Remember Correctly = Falls ich mich richtig erinnere OT = Off Topic = Am Thema (der Liste) vorbei |Zufallssignatur 11
On Die, 17 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 17.Jul.2001:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Wenn es nicht funktioniert, dann sollte da aber schon eine Fehlermeldung kommen. Kommt doch sonst nie einer drauf, daß es an der Nichtanlegbarkeit (was für ein Wort ;)) der Tempdatei liegt.
Hast du's getestet? Das ist naemlich Absicht, dass da nur das exit 1 steht: $ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd Leider gibt mktemp nicht auch den Grund aus... Laesst sich aber leicht einbauen: ==== mit mktemp-VERSION-linux.patch (von djb) ==== void err(int somecode, char * message, ...) { va_list arglist; va_start(arglist, message); vfprintf(stderr, message, arglist); fprintf(stderr, ": %s\n", strerror(errno)); ==== /* ^^^^ ^^^^^^^^^^^^^^^^^ */ ==== das unterstrichene hinzufuegen... Ohne den patch wird die Ursache eh schon ausgegeben... (alles bzgl. mktemp-1.5).
Das $$ ist hier eigentlich nicht mehr nötig. mktemp macht einen Einzigartigen Namen.
Naja, "einzigartig" halt im Rahmen von mkstemp... Und "sicher" ist die in mkstemp verwendete Funktion __gen_tempname nicht... ==== aus glibc-2.1.3/sysdeps/posix/tempname.c We use a clever algorithm to get hard-to-predict names. */ ==== Das macht schon stutzig ==== [..] /* Get some more or less random data. */ __gettimeofday (&tv, NULL); value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ __getpid (); for (count = 0; count < TMP_MAX; value += 7777, ++count) { uint64_t v = value; /* Fill in the random bits. */ XXXXXX[0] = letters[v % 62]; v /= 62; [..das gleiche bis 4..] XXXXXX[5] = letters[v % 62]; ==== Kryptographisch "sicher" ist das IMO nicht. Aber es sollte fuer die meisten Faelle "langen"...
Nur sowas wie ${prg} schriebe ich auch davor, denn dann hat man eine bessere Chance herauszubekommen, was das für eine Datei ist.
Ack!
Naja, ich muss zugeben, dass ich fast lieber noch ein "festes" Namens- schema fuer meine tmp-dateien nehme, z.B. /tmp/${prg}.$$.temp (und dann ein 'trap "rm $temp_file; exit 1" 1 2 3 6 7 13 15' mit einbaue... Was spricht gegen diese Zeile, wenn Du temp_file vorher wie oben definiert hast, also mit mktemp? Dann kanst Du es genauso in Deiner trap aufnehmen oder später sonstwie wegräumen.
Ja klar, das trap gehoert immer rein.
Je nach script durchaus aber auch einfach nur ein /tmp/${prg}.tmp (!!) das gnadenlos ueberschrieben/geleert/geloescht wird... Motto: Alles in /tmp darf jederzeit geloescht werden *eg*
Damit sollte man rechnen. Ist ja auch eine Frage, was das Programm macht. Kann sein, daß es nicht so wichtig ist, dann ist es egal. Wenn es entscheident ist, dann muß man Vorsorge treffen, wenn die tempdatei nicht mehr da ist.
Jup. -dnh -- "Now, what was I doing before I so rudely interrupted myself?"
* David Haller schrieb am 18.Jul.2001:
On Die, 17 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 17.Jul.2001:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Wenn es nicht funktioniert, dann sollte da aber schon eine Fehlermeldung kommen. Kommt doch sonst nie einer drauf, daß es an der Nichtanlegbarkeit (was für ein Wort ;)) der Tempdatei liegt.
Hast du's getestet? Das ist naemlich Absicht, dass da nur das exit 1 steht:
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen? Der weiß doch gar nicht was ein tempfile ist. Auch hier ist perl flexiebler.
Das $$ ist hier eigentlich nicht mehr nötig. mktemp macht einen Einzigartigen Namen.
Naja, "einzigartig" halt im Rahmen von mkstemp... Und "sicher" ist die in mkstemp verwendete Funktion __gen_tempname nicht...
Mist. Habe ich nicht ausprobiert. Ich kannte mktemp bisher nur so, daß es a$$.tmp oder so ähnlich ausgab. Sollte genau dies schon existieren, so gab es b$$.tmp aus usw. Halte ich für viel vernünftiger. Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen. Dabei benutze ich mktemp mehrfach. Ich sollte mir mal die Tempfiles angeschaut haben. ;) Hmm, in einen Fall, habe ich es sogar recht häufig gemacht, aber nicht auf dem Namen geachtet. Der $0-Bestandteil hatte zum Auffinden gereicht. ;)) Dann schlage ich sowas wie ${prg}.`date +%s`.$$.tmp vor. Da gibt es so schnell keine doppelte, es sei denn es werden im Prozeß selber mehere tmp angelegt. Die kann ich dann aber hart anders nennen, etwa: $TMP1=$TMPDIR/$PRG.A`date +%s`.$$.tmp $TMP2=$TMPDIR/$PRG.B`date +%s`.$$.tmp $TMP3=$TMPDIR/$PRG.C`date +%s`.$$.tmp Sollte man in einer Schleife Tempdateien anlegen (könnte ja sein, daß man das braucht. ;)) dann wird der Schleifenzähler mit im Namen aufgeführt.
Kryptographisch "sicher" ist das IMO nicht.
Was hat das mit Kryptographie zu tun? Auch wenn es echte Zufallszahlen sind, wird Gleichheit nicht ausgeschlossen.
Naja, ich muss zugeben, dass ich fast lieber noch ein "festes" Namens- schema fuer meine tmp-dateien nehme, z.B. /tmp/${prg}.$$.temp (und dann ein 'trap "rm $temp_file; exit 1" 1 2 3 6 7 13 15' mit einbaue...
Was spricht gegen diese Zeile, wenn Du temp_file vorher wie oben definiert hast, also mit mktemp? Dann kanst Du es genauso in Deiner trap aufnehmen oder später sonstwie wegräumen.
Ja klar, das trap gehoert immer rein.
Was mir an Deiner trap-Zeile auffällt, Du fängst Signal 14 nicht ab. alarm ist doch nett um einen Prozeß zu einem bestimmten Zeitpunkt zu beenden. Gibt es keinen Userbefehl, der alarm verwendet? Ich meine, da gäbe es was. Ich weiß, daß ich es früher mehrfach benutzt habe. Kann aber sein, daß das C war und ich alarm direkt benutzt habe. Bernd -- Probleme mit dem Drucker? Schon die Druckercheckliste beachtet? http://localhost/doc/sdb/de/html/drucker-howto.html | Auch lesenswert: Oder schon das Drucker-HOWTO gelesen? | man lpr file://usr/shar/doc/howto/de/DE-Drucker-HOWTO.txt.gz | Zufallssignatur 3
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001:
On Die, 17 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 17.Jul.2001:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
Wenn es nicht funktioniert, dann sollte da aber schon eine Fehlermeldung kommen. Kommt doch sonst nie einer drauf, daß es an der Nichtanlegbarkeit (was für ein Wort ;)) der Tempdatei liegt.
Hast du's getestet? Das ist naemlich Absicht, dass da nur das exit 1 steht:
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status). Allerdings habe ich gesehen, dass die originale Version von mktemp durchaus auch strerror(errno) ausgibt, das hat der patch (-linux.patch) eben ueberschrieben.
Der weiß doch gar nicht was ein tempfile ist. Auch hier ist perl flexiebler.
Das mag sein. Und ich denke die beste Loesung ist eh, die Meldung von mktemp (samt strerror(errno) wg. dem Grund, s.o) auszugeben, und dann zusaetzlich evtl. noch eine eigene... Aber das haengt natuerlich auch stark von dem Umstaenden ab, in denen die temporaere Datei benoetigt wird...
Das $$ ist hier eigentlich nicht mehr nötig. mktemp macht einen Einzigartigen Namen.
Naja, "einzigartig" halt im Rahmen von mkstemp... Und "sicher" ist die in mkstemp verwendete Funktion __gen_tempname nicht...
Mist. Habe ich nicht ausprobiert. Ich kannte mktemp bisher nur so, daß es a$$.tmp oder so ähnlich ausgab. Sollte genau dies schon existieren, so gab es b$$.tmp aus usw. Halte ich für viel vernünftiger.
Nein, mktemp macht mittels der libc-Funktion 'mkstemp' (siehe die manpage dazu), aus "VORLAGEXXXXXX" ein "VORLAGEZZZZZZ" wobei ZZZZZZ das generierte "eindeutige" Muster ist (aus a-z A-Z 0-9). mkstemp wiederum verwendet die (libc-interne) posix-funktion __gen_tempname um aus das sechststellige Muster zu erzeugen, mit dem das XXXXXX in der Vorlage ersetzt wird.
Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen.
Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits") zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler- ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
Dabei benutze ich mktemp mehrfach. Ich sollte mir mal die Tempfiles angeschaut haben. ;) Hmm, in einen Fall, habe ich es sogar recht häufig gemacht, aber nicht auf dem Namen geachtet. Der $0-Bestandteil hatte zum Auffinden gereicht. ;))
*g*
Dann schlage ich sowas wie
${prg}.`date +%s`.$$.tmp vor. Da gibt es so schnell keine doppelte, es sei denn es werden im Prozeß selber mehere tmp angelegt. Die kann ich dann aber hart anders nennen, etwa:
$TMP1=$TMPDIR/$PRG.A`date +%s`.$$.tmp $TMP2=$TMPDIR/$PRG.B`date +%s`.$$.tmp $TMP3=$TMPDIR/$PRG.C`date +%s`.$$.tmp
Sollte man in einer Schleife Tempdateien anlegen (könnte ja sein, daß man das braucht. ;)) dann wird der Schleifenzähler mit im Namen aufgeführt.
Ack.
Kryptographisch "sicher" ist das IMO nicht.
Was hat das mit Kryptographie zu tun? Auch wenn es echte Zufallszahlen sind, wird Gleichheit nicht ausgeschlossen.
Naja, um die Gleichheit geht es auch nicht (es gibt fuer das Muster immerhin 62^6 = 56.800.235.584 Moeglichkeiten). Das Problem ist, wie das Muster erzeugt wird (d.h. mit welchem Aufwand es zu vorherzusagen ist...) Und da ist das "clevere" Schema das in __gen_tempname verwendet wird nicht sonderlich, Es heisst: ==== /* Get some more or less random data. */ __gettimeofday (&tv, NULL); value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ __getpid (); ==== d.h. es wird die Zeit (theoretisch auf die Mikrosekunde) genau und die PID verwurstet. Allerdings sind beide Datenquellen nicht als "zufaellig" einzustufen. Die PID laesst sich sowieso leicht heraus- finden und die Zeit, zu der das __gettimeofday() aufgerufen laesst, laesst sich (vermute ich) mit tests ebenfalls (hinreichend) genau vorhersagen. Das restliche Verwursten dieser Daten ist dann einfach. Besser waere es wohl, sich die 64 bit Daten aus /dev/random zu besorgen, aber /dev/random ist halt (AFAIK) nicht im POSIX Standard... (Siehe dazu /usr/src/linux/drivers/char/random.c (den Anfangskommentar) und man 4 random). Das "sicher" bezieht auf die Vorhersagbarkeit... Wolfgang koennte zu den Folgen der (von mir vermuteten Vorhersagbarkeit) noch einiges mehr sagen... Aber wie gesagt, ich denke, dass die (Nicht-)Vorhersagbarkeit von __gen_tempname (und somit von mkstemp(3) und mktemp(1)) fuer die meisten Faelle ausreicht (also schwierig genug ist)...
Was mir an Deiner trap-Zeile auffällt, Du fängst Signal 14 nicht ab.
Oh, das war nur kurz hingeschludert, SIGALRM hab ich schlicht uebersehen ;) -dnh --
Blame directed at the wrong vendor tends to get reclassified as whining. No worries, I'm good at that too. -- Chris Hacking and Jay Mottern in asr
* David Haller schrieb am 18.Jul.2001:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001:
On Die, 17 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 17.Jul.2001:
On Mon, 16 Jul 2001, Jan Trippler wrote:
On Mon, 16 Jul 2001 at 19:39 (+0200), David Haller wrote:
> tmp_datei="`mktemp /tmp/${prg}.$$.XXXXXX`" || exit 1
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Das ist richtig. Aber wenn ich mktemp in einer Anwendung benutze, die wiederum von einem anderen Skript benutzt wird, dann kann der Endanwender nichts damit anfangen, daß mktemp nicht funktioniert. Welches mktemp?
Der weiß doch gar nicht was ein tempfile ist. Auch hier ist perl flexiebler.
Das mag sein. Und ich denke die beste Loesung ist eh, die Meldung von mktemp (samt strerror(errno) wg. dem Grund, s.o) auszugeben, und dann zusaetzlich evtl. noch eine eigene... Aber das haengt natuerlich auch stark von dem Umstaenden ab, in denen die temporaere Datei benoetigt wird...
Klar, allerdings, wenn es sich nur um so ein Miniwegwerfskript handelt, dann benutze ich erst gar nicht mktemp. Wenn es sich aber um ein Skript für den ständigen Gebrauch handelt, dann werde ich auch selber in einem Jahr nicht mehr wissen, wie und wo da mktemp benutzt wurde. Geschweige ein Anderer.
Mist. Habe ich nicht ausprobiert. Ich kannte mktemp bisher nur so, daß es a$$.tmp oder so ähnlich ausgab. Sollte genau dies schon existieren, so gab es b$$.tmp aus usw. Halte ich für viel vernünftiger.
Nein, mktemp macht mittels der libc-Funktion 'mkstemp' (siehe die manpage dazu), aus "VORLAGEXXXXXX" ein "VORLAGEZZZZZZ" wobei ZZZZZZ das generierte "eindeutige" Muster ist (aus a-z A-Z 0-9).
Ich meinte den XXXXX-Teil. Das mit der VORLAGE habe ich auch so in Erinnerung.
mkstemp wiederum verwendet die (libc-interne) posix-funktion __gen_tempname um aus das sechststellige Muster zu erzeugen, mit dem das XXXXXX in der Vorlage ersetzt wird.
Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen.
Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits") zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler- ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
Ägypten? Ich erwarte von mktemp, daß wenn es feststellt, daß der von ihm gewählten Namen schon existiert, einfach einen anderen nimmt. Solange bis es einen gefunden hat.
Kryptographisch "sicher" ist das IMO nicht.
Was hat das mit Kryptographie zu tun? Auch wenn es echte Zufallszahlen sind, wird Gleichheit nicht ausgeschlossen.
Naja, um die Gleichheit geht es auch nicht (es gibt fuer das Muster immerhin 62^6 = 56.800.235.584 Moeglichkeiten). Das Problem ist, wie das Muster erzeugt wird (d.h. mit welchem Aufwand es zu vorherzusagen ist...) Und da ist das "clevere" Schema das in __gen_tempname verwendet wird nicht sonderlich, Es heisst:
==== /* Get some more or less random data. */ __gettimeofday (&tv, NULL); value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ __getpid (); ====
d.h. es wird die Zeit (theoretisch auf die Mikrosekunde) genau und die PID verwurstet. Allerdings sind beide Datenquellen nicht als "zufaellig" einzustufen. Die PID laesst sich sowieso leicht heraus- finden und die Zeit, zu der das __gettimeofday() aufgerufen laesst, laesst sich (vermute ich) mit tests ebenfalls (hinreichend) genau vorhersagen. Das restliche Verwursten dieser Daten ist dann einfach.
Besser waere es wohl, sich die 64 bit Daten aus /dev/random zu besorgen, aber /dev/random ist halt (AFAIK) nicht im POSIX Standard... (Siehe dazu /usr/src/linux/drivers/char/random.c (den Anfangskommentar) und man 4 random).
Das "sicher" bezieht auf die Vorhersagbarkeit...
Was ist schlimm an Vorhersagbarkeit? Was ich will ist Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne, die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist Einzigartig, genau das was ich will. Allerdings müßten alle Programme, die temporäre Dateien benutzen dieses Schema benutzen.
Wolfgang koennte zu den Folgen der (von mir vermuteten Vorhersagbarkeit) noch einiges mehr sagen...
Aber wie gesagt, ich denke, dass die (Nicht-)Vorhersagbarkeit von __gen_tempname (und somit von mkstemp(3) und mktemp(1)) fuer die meisten Faelle ausreicht (also schwierig genug ist)...
Ich verstehe immer noch nicht, was da so schlimm dran sein soll. Was kann der Angreifer machen, wenn er weiß, wie die nächste temporäre Datei heißt? Er darf natürlich von Anfang an keine Schreibrechte darauf haben. Am Besten auch keine Leserechte. Wenn diese Datei schon existiert, wird sie nicht angelegt, sondern ein anderen Namen gewählt. Also kann der Angreifer da auch keine Fallen aufbauen. Habe ich da was übersehen? Vielleicht den kurzen Moment, der vom Test auf Existenz bis zur tatsächlichen Anlegung vergeht? Aber das Problem habe ich immer. Bernd -- ACK = ACKnowledge = Zustimmung | NAC = No ACknowledge = keine Zustimmung DAU = Dümmster Anzunehmender User | LOL = Laughing Out Loud = Lautes Lachen IIRC = If I Remember Correctly = Falls ich mich richtig erinnere OT = Off Topic = Am Thema (der Liste) vorbei |Zufallssignatur 11
Hallo! On Thursday, 19. July 2001 09:17, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [Einzigartigkeit von temporären Dateien]
Das "sicher" bezieht auf die Vorhersagbarkeit...
Was ist schlimm an Vorhersagbarkeit? Was ich will ist Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne, die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist Einzigartig, genau das was ich will. Allerdings müßten alle Programme, die temporäre Dateien benutzen dieses Schema benutzen.
Das Schlimme an Verhersagbarkeit ist die Möglichkeit eines lokalen Angriffs. Stell Dir ein Skript von root vor, dass in eine temporäre Datei schreibt (ohne vorher deren _Nicht_existenz geprüft zu haben). Ein Angreifer muss nur den Namen dieser temporären Datei voraussagen und einen Link unter diesem Namen auf eine beliebige Datei legen, die daraufhin überschrieben wird. Ein beliebtes Ziel ist /etc/passwd. Ich habe den Thread nicht komplett verfolgt. Möglicherweise ist das im Vorfeld auch schon geschrieben worden. Gruß, Stephan -- Stephan Hakuli | mailto: stephan@hakuli.de | * GnuPG/PGP-Key * | callto: 01 71 - 651 89 43 | available, please | surfto: http://www.hakuli.de | visit my homepage
* Stephan Hakuli schrieb am 19.Jul.2001:
On Thursday, 19. July 2001 09:17, Bernd Brodesser wrote:
[Einzigartigkeit von temporären Dateien]
Was ist schlimm an Vorhersagbarkeit? Was ich will ist Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne, die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist Einzigartig, genau das was ich will. Allerdings müßten alle Programme, die temporäre Dateien benutzen dieses Schema benutzen.
Das Schlimme an Verhersagbarkeit ist die Möglichkeit eines lokalen Angriffs. Stell Dir ein Skript von root vor, dass in eine temporäre Datei schreibt (ohne vorher deren _Nicht_existenz geprüft zu haben). Ein Angreifer muss nur den Namen dieser temporären Datei voraussagen und einen Link unter diesem Namen auf eine beliebige Datei legen, die daraufhin überschrieben wird. Ein beliebtes Ziel ist /etc/passwd.
Auch deshalb muß überprüft werden, ob die Datei schon existiert oder nicht. Wäre ja auch blöde, wenn root anfängt irgendwo reinzuschreiben, wenn die Datei nur zufällig so heißt, und keine böse Absicht besteht. Was ist an dem alten Vorgehen zu bemängeln, daß mktemp das XXXXX in VORGABEXXXXX durch a$$ ersetzt? Wenn das schon existierte, dann machte es daraus ein b$$ usw. Dieses Verhalten hatten HP_UX Maschinen vor ca. 10 Jahren. Bernd -- Umsteiger von Microsoft Windows xx? Hast Du schon file://usr/doc/howto/de/DE-DOS-nach-Linux-HOWTO.txt gelesen? Auch file://usr/doc/Books/Linuxhandbuch.dvi ist zu empfehlen. |Zufallssignatur 1
On Don, 19 Jul 2001 at 13:36 (+0200), Bernd Brodesser wrote: [...]
Was ist an dem alten Vorgehen zu bemängeln, daß mktemp das XXXXX in VORGABEXXXXX durch a$$ ersetzt? Wenn das schon existierte, dann machte es daraus ein b$$ usw. Dieses Verhalten hatten HP_UX Maschinen vor ca. 10 Jahren.
Neben den (sicher ziemlich seltenen) Angriffspunkten für einen böswilligen Benutzer, wie sie David genannt hat, sind a$$ bzw. b$$ sehr kurz und damit ist die Wahrscheinlichkeit, dass diese Dateien existieren, ziemlich hoch. Damit kommt man (bei Maschinen, auf denen sich ein reges Tierleben in /tmp abspielt) sehr schnell in die Situation, dass ein neuer mktemp sehr viele Dateinamen abklappern muss, um einen freien zu finden (mir fällt gerade auf, dass dies bei allen systematischen, also nach einer Reihenfolge vorgehenden Algorithmen so ist - unabhängig von der Länge des Dateinamens). Und das ist der Performance nicht zuträglich. Ein mehr oder weniger zufällig arbeitender Mechanismus findet schneller einen freien Namen. Die Anzahl der Versuche bei einem systematischen Algorithmus kannst Du ganz einfach ausrechnen: Jeder neue mktemp braucht einen Schritt mehr (es sei denn, inzwischen sind wieder ein paar Dateien gelöscht worden). Jan
On Don, 19 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [..]
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Das ist richtig. Aber wenn ich mktemp in einer Anwendung benutze, die wiederum von einem anderen Skript benutzt wird, dann kann der Endanwender nichts damit anfangen, daß mktemp nicht funktioniert. Welches mktemp?
mktemp(1). Sollte via foo=`mktemp ...` || exit $? klappen, wenn denn mktemp(1) mit exit(errno) aussteigen wuerde... (was es leider nicht tut, aber IMO meist auch nicht noetig ist). Und ein Cannot create temp file /root/test.YTRUBd: Permission denied waere IMO relativ aussagekraeftig, wenn das "Permission denied" in der SuSE Version (und anderen) nicht weggepatcht waere... (wobei das "Permission denied" dank strerror auf deutsch kaeme).
Klar, allerdings, wenn es sich nur um so ein Miniwegwerfskript handelt, dann benutze ich erst gar nicht mktemp. Wenn es sich aber um ein Skript für den ständigen Gebrauch handelt, dann werde ich auch selber in einem Jahr nicht mehr wissen, wie und wo da mktemp benutzt wurde. Geschweige ein Anderer.
Ack. Mach ich ja auch ;)
Ich meinte den XXXXX-Teil. Das mit der VORLAGE habe ich auch so in Erinnerung.
Siehe man 3 mkstemp. Da ist der Mechanismus mit dem XXXXXX erklaert.
Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen.
Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits") zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler- ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
Ägypten?
Kairo? (*nixblick*)
Ich erwarte von mktemp, daß wenn es feststellt, daß der von ihm gewählten Namen schon existiert, einfach einen anderen nimmt. Solange bis es einen gefunden hat.
Genau _das_, das alternativen testen, macht keine der Funktionen (bzw. mktemp(1)). Darum muss man sich selbst kuemmern. z.B. in der bash mit: while ! tmpfile=`mktemp vorlage.XXXXXX`; do : ; done (ggfs. noch mit nem schleifenzaehler um irgendwann abzubrechen).
Kryptographisch "sicher" ist das IMO nicht.
Was hat das mit Kryptographie zu tun? Auch wenn es echte Zufallszahlen sind, wird Gleichheit nicht ausgeschlossen.
Naja, um die Gleichheit geht es auch nicht (es gibt fuer das Muster immerhin 62^6 = 56.800.235.584 Moeglichkeiten). Das Problem ist, wie das Muster erzeugt wird (d.h. mit welchem Aufwand es zu vorherzusagen ist...) Und da ist das "clevere" Schema das in __gen_tempname verwendet wird nicht sonderlich, [schnippel] Das "sicher" bezieht auf die Vorhersagbarkeit...
Was ist schlimm an Vorhersagbarkeit? Was ich will ist Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne, die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist Einzigartig, genau das was ich will. Allerdings müßten alle Programme, die temporäre Dateien benutzen dieses Schema benutzen.
Das hat mir Wolfgang mal erklaert hat (IIRC im Zusammenhang mit meine "toggle-a-attr", das IIRC anfangs auch ueber die Liste ging)... (s.u.)
Wolfgang koennte zu den Folgen der (von mir vermuteten Vorhersagbarkeit) noch einiges mehr sagen...
Aber wie gesagt, ich denke, dass die (Nicht-)Vorhersagbarkeit von __gen_tempname (und somit von mkstemp(3) und mktemp(1)) fuer die meisten Faelle ausreicht (also schwierig genug ist)...
Ich verstehe immer noch nicht, was da so schlimm dran sein soll. Was kann der Angreifer machen, wenn er weiß, wie die nächste temporäre Datei heißt? Er darf natürlich von Anfang an keine Schreibrechte darauf haben. Am Besten auch keine Leserechte. Wenn diese Datei schon existiert, wird sie nicht angelegt, sondern ein anderen Namen gewählt. Also kann der Angreifer da auch keine Fallen aufbauen. Habe ich da was übersehen?
Ja. Reingefallen. Wie ich auch... :) Ein Szenario folgt (das aber, wie ich schrieb, fuer die meisten Faelle wenig bis nicht relevant ist, aber wir reden hier ja inzwischen um's Prinzip, oder? Darueber, dass mktemp in der Praxis (fast) immer ausreicht sind wie uns glaub einig...) Ach ja, ob und wie man das genannte Problem "remote" ausnuezten koennte weiss ich nicht, Wolfgang wuesste da mehr, aber es waere AFAIK moeglich sich als lokaler user (und somit ggfs. via einem solchen auch remote) mit root-Rechten zu agieren (oder sogar diese zu erlangen?)
Vielleicht den kurzen Moment, der vom Test auf Existenz bis zur tatsächlichen Anlegung vergeht? Aber das Problem habe ich immer.
Ja. So in etwa.... - Angreifer erlangt "user-Rechte" auf einer Kiste (egal wie). - A macht einen benchmark auf die Verzoegerung zwischen Aufruf von mktemp(1) und dem __gettimeofday [1] in __gen_tempname. Je ungenauer die tatsaechliche "Zeitaufloesung" auf der HW ist (in Bezug zu den Mikrosekunden die in __gen_tempname verwendet werde), umso einfacher wird IMO der Angriff. - A schreibt einen exploit, der anhand der Voraussage der Latenz zwischen dem mktemp Aufruf und dem __gettimeofday sehr vereinfacht wird, und der (millonenfach) versucht die Ausgabe des __gettimeofday vorherzusagen. - hat A einen "Treffer" erzielt ist die PID (via dem __getpid [2]) trivial. Aus diesen Daten kann die Ausgabe von __gen_tempname vorhergesagt werden. (Wobei die laenger dauernden Funktionen wie evtl. getpid natuerlich passen vorverlagert werden muessen) - A kann also mit einer hinreichenden Genauigkeit "voraussagen" was mktemp generieren wird (beim naechsten Aufruf generieren wuerde). - A "weiss" den Namen der tempdatei bevor es der legitime Nutzer weiss. - Zwei Moeglichkeiten: a) mktemp kann von A mit dem Parameter -u aufgerufen werden, der die tempdatei unlinkt (man 2 unlink). => ln -sf /etc/passwd tempfile und mktemp loescht fuer A /etc/passwd, dass A dann ganz nach Geschmack neu anlegen kann, oder wenn /etc/ passende Rechte hat, ist /etc/passwd auch nur einfach weg. b) A klinkt sich mit einem aehnlichen Angriff "mittenrein" in mktemp(1)/mkstemp(3)/__gen_tempname und kann ebenfalls beliebige Dateien so verlinken, dass er die Rechte daran hat (die Details weiss ich leider nicht mehr, bin mir aber recht sicher, dass das gehen wuerde). Insgesamt ergibt sich, dass __gen_tempname (und somit mkstemp(3), mktemp(1), und mehr noch mktemp(3)) nicht wirklich "sicher" sind, auch wenn diese Sicherheit wohl fuer die meisten Faelle in der Praxis ausreicht. Aus man 3 mktemp: BUGS Never use mktemp(). Some implementations follow BSD 4.3 and replace XXXXXX by the current process id and a single letter, so that at most 26 different names can be ^^^^^^^^^^^^^ returned. Since on the one hand the names are easy to guess, and on the other hand there is a race between test ing whether the name exists and opening the file, every use of mktemp() is a security risk. The race is avoided by mkstemp(3). Das ist eben nicht wirklich richtig, denn die "Race Condition" wird nicht umgangen (avoided), sondern es wird nur um deutlich schwerer, aber eben IMO laengst nicht unmoeglich, die Namen vorherzusagen. Einmal dadurch, dass es potentiell 62^6 namen gibt (aber die PID wird zur Erzeugung verwendet, wie genau hab ich nicht analysiert, und die PID ist sozusagen "vorhanden", d.h. die eigentlichen Moeglichkeiten werden um ein paar Groessenordnungen verringert). Kurz und gut: Die Sicherheit von __gen_tempname (und abegeleitete) beruht auf der Vorhersagbarkeit von __gettimeofday(), und die _ist_ vorherzusagen... Wenn du das mit den Kommentaren am Anfang von /usr/src/linux/drivers/char/random.c vergleichst, insbesondere, welche wesentlich zufaelligeren Datenquellen im Vergleich zu __gettimeofday verwendet werden, wirst du sehen, dass das _vergleichsweise_ unsicher ist (auch wenn es fuer die meisten _praktischen_ Faelle ausreichen sollte. Ein "sicheres" __gen_tempname wuerde also nicht 64 bit aus __gettimeofday + PID sondern 64 bit aus /dev/random verwenden, das u.a. Tastatur(Taste, Zeitpunkt), Maus (Position, Klicks, Zeitpunkt), HD (Zeit von IO ops), IRQs (Zeitpunkt) allgemein verwendet und mit (wenn nicht) der beste Zufallsgenerator auf PCs ist. Und nur, damit keine Missverstaendnisse aufkommen: Fuer (fast) alle praktischen Anwendungen ist __gen_tempname (also auch mkstemp und mktemp) sicher genug! Und auch die zeitliche Aufloesung von __gettimeofday sollte fuer (fast) alle Anwendungen "reichen" um zusaetzliche Sicherheit zu gewaehrleisten. Leider bin ich weder in C noch in der Kryptographie bewandert genung um auch nur eine Abschaetzung der Sicherheit (d.h. des Aufwandes, um z.B. oben skizzierten Angriff durchzufuehren) zu wagen... Um nochmal zusammenzufassen: Die (pauschale(!!!)) Aussage __gen_tempname (und somit mkstemp(3) und somit mktemp(1)) sei "sicher" ist falsch! Die Aussage __gen_tempname sei sicher _genug_ fuer *fast* alle Anwendungen ist IMO richtig! Und nochmal: Die "Eindeutigkeit" des erzeugten Muster ist mit 62^6 IMO gut genug, die "Schwaeche" ist die Vorhersagbarkeit des Ergebnisses (egal in welcher Stufe, sei's noch innerhalb von __gen_tempname, sei's in mkstemp(3) oder sei's in mktemp(1)). Die "Guete" von 62^6 ist aber nur gleichzusetzen mit einer "Schluessel- laenge" x von 35 bit < x < 36 Bit... Und das ist heutzutage kein Problem. Und da gettimeofday quasi fuer jeden beliebigen Zeitpunkt im Voraus(!)[3] berechnet werden kann (und die PID ein "piece of cake" ist)... Hmm. Sowenig das ganze mit der Praxis zu tun haben mag (das kann und will ich nicht beurteilen, ich bin kein Hacker und erst recht kein Cracker), so hoffe ich doch, das "blinde" Vertrauen erschuettert zu haben und, wie Wolfgang es bei mir in Sachen Race-Conditions etc. generell tat, auch bei dir (und anderen?) ein gewisses, gesundes Misstrauen und vielleicht auch Interesse an der Problematik geweckt zu haben. Ja, klar fuer die 08/15 Kiste ist sogar mktemp vielleicht schon overkill, aber fuer Rechner, die sicher sein muessen, ist IMO eine bessere Version von mkstemp (s.o., mit /dev/random) zu verwenden... Und ja, auf solchen Kisten, sollte man wohl die GNU libc sowieso nicht verwenden ;) -dnh P.S: Ja, das "clever" in __gen_tempname hat mich stutzig gemacht... PPS: Nein, ich bin kein Sicherheitsfetischist, ich hab weder eine Firewall am laufen noch einen aktuellen PGP/GPG Key... ABER: Ich denke ich habe eine gewisse Idee, wie unsicher meine Kiste ist... Und darauf kommt's IMO an, sich der Problematik bewusst zu sein. Da faellt mir ein Spruch ein, den ich leider noch nicht gesiggt habe und daher einfach mal sinngemaess auf deutsch statt auf englisch wiedergebe: "Das einzige sichere System, ist in einem Safe, in einem 10m^3 Betonblock und versenkt im Marianengraben" Und ne "echte" sig, die dazu passt *eg*: The only truly safe "embedded system" is the system that has an axe embedded in it... -- Tanuki [1] siehe man 2 gettimeofday, das __ kommt innerhalb der libc dazu [2] man 2 getpid [3] also mit "beliebigem" Aufwand -- no amount of Zen contemplation will ever make you at one with a 3c905B ethernet card. -- Alan Cox
* David Haller schrieb am 19.Jul.2001:
On Don, 19 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [..]
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Das ist richtig. Aber wenn ich mktemp in einer Anwendung benutze, die wiederum von einem anderen Skript benutzt wird, dann kann der Endanwender nichts damit anfangen, daß mktemp nicht funktioniert. Welches mktemp?
mktemp(1).
;) Aber der User versteht es nicht. Der braucht keine man-pages zu kennen.
Cannot create temp file /root/test.YTRUBd: Permission denied
Wenn das so manchen User vorgelegt wird, dann weigert er sich noch weiter an diesem Rechner zu arbeiten, bis ein Geisterbeschwörer die Tastatur und den Bildschirm ausgependelt hat und bestätigt hat, daß eine weitere Benutzung des Rechners nicht notwendig einen Weltkrieg auslöst. "Was soll YTRUBd sein, und wie ließt man das?"
Ich erwarte von mktemp, daß wenn es feststellt, daß der von ihm gewählten Namen schon existiert, einfach einen anderen nimmt. Solange bis es einen gefunden hat.
Genau _das_, das alternativen testen, macht keine der Funktionen (bzw. mktemp(1)). Darum muss man sich selbst kuemmern. z.B. in der bash mit:
Dann ist das aber ein Gewaltiger Rückschritt. Wenn ich mich Recht erinnere und nicht völlig daneben liege, hat das eine HP_UX-Kiste genau so gemacht. Hatte ich mal durchgetestet. Da hat er Anstelle von a$$ eben b$$ geschrieben.
while ! tmpfile=`mktemp vorlage.XXXXXX`; do : ; done
(ggfs. noch mit nem schleifenzaehler um irgendwann abzubrechen).
Das "sicher" bezieht auf die Vorhersagbarkeit...
Was ist schlimm an Vorhersagbarkeit? Was ich will ist Einzigartigkeit. Das ist wichtig. Wenn ich eine Datei temp1 nenne, die nächste temp2 usw. so ist das absolut vorhersehbar, aber es ist Einzigartig, genau das was ich will. Allerdings müßten alle Programme, die temporäre Dateien benutzen dieses Schema benutzen.
Das hat mir Wolfgang mal erklaert hat (IIRC im Zusammenhang mit meine "toggle-a-attr", das IIRC anfangs auch ueber die Liste ging)... (s.u.)
Wolfgang koennte zu den Folgen der (von mir vermuteten Vorhersagbarkeit) noch einiges mehr sagen...
Aber wie gesagt, ich denke, dass die (Nicht-)Vorhersagbarkeit von __gen_tempname (und somit von mkstemp(3) und mktemp(1)) fuer die meisten Faelle ausreicht (also schwierig genug ist)...
Ich verstehe immer noch nicht, was da so schlimm dran sein soll. Was kann der Angreifer machen, wenn er weiß, wie die nächste temporäre Datei heißt? Er darf natürlich von Anfang an keine Schreibrechte darauf haben. Am Besten auch keine Leserechte. Wenn diese Datei schon existiert, wird sie nicht angelegt, sondern ein anderen Namen gewählt. Also kann der Angreifer da auch keine Fallen aufbauen. Habe ich da was übersehen?
Ja. Reingefallen. Wie ich auch... :)
Ein Szenario folgt (das aber, wie ich schrieb, fuer die meisten Faelle wenig bis nicht relevant ist, aber wir reden hier ja inzwischen um's Prinzip, oder?
Ja.
Darueber, dass mktemp in der Praxis (fast) immer ausreicht sind wie uns glaub einig...)
Ja, obwohl wenn das blöde Teil noch nicht mal testet.
Ach ja, ob und wie man das genannte Problem "remote" ausnuezten koennte weiss ich nicht, Wolfgang wuesste da mehr, aber es waere AFAIK moeglich sich als lokaler user (und somit ggfs. via einem solchen auch remote) mit root-Rechten zu agieren (oder sogar diese zu erlangen?)
gehen wir von local aus. Das ein remote-Angreifer zuerst versucht sich als User einzuloggen ist klar.
Vielleicht den kurzen Moment, der vom Test auf Existenz bis zur tatsächlichen Anlegung vergeht? Aber das Problem habe ich immer.
Ja. So in etwa....
- Angreifer erlangt "user-Rechte" auf einer Kiste (egal wie).
- A macht einen benchmark auf die Verzoegerung zwischen Aufruf von mktemp(1) und dem __gettimeofday [1] in __gen_tempname. Je ungenauer die tatsaechliche "Zeitaufloesung" auf der HW ist (in Bezug zu den Mikrosekunden die in __gen_tempname verwendet werde), umso einfacher wird IMO der Angriff.
- A schreibt einen exploit, der anhand der Voraussage der Latenz zwischen dem mktemp Aufruf und dem __gettimeofday sehr vereinfacht wird, und der (millonenfach) versucht die Ausgabe des __gettimeofday vorherzusagen.
- hat A einen "Treffer" erzielt ist die PID (via dem __getpid [2]) trivial. Aus diesen Daten kann die Ausgabe von __gen_tempname vorhergesagt werden.
Lassen wir das doch mal weg. Angenommen er kennt den Namen exakt.
(Wobei die laenger dauernden Funktionen wie evtl. getpid natuerlich passen vorverlagert werden muessen)
- A kann also mit einer hinreichenden Genauigkeit "voraussagen" was mktemp generieren wird (beim naechsten Aufruf generieren wuerde).
Nehmen wir an er weiß es genau.
- A "weiss" den Namen der tempdatei bevor es der legitime Nutzer weiss.
Ja, das nehmen wir an.
- Zwei Moeglichkeiten:
a) mktemp kann von A mit dem Parameter -u aufgerufen werden, der die tempdatei unlinkt (man 2 unlink). => ln -sf /etc/passwd tempfile und mktemp loescht fuer A /etc/passwd, dass A dann ganz nach Geschmack neu anlegen kann, oder wenn /etc/ passende Rechte hat, ist /etc/passwd auch nur einfach weg.
b) A klinkt sich mit einem aehnlichen Angriff "mittenrein" in mktemp(1)/mkstemp(3)/__gen_tempname und kann ebenfalls beliebige Dateien so verlinken, dass er die Rechte daran hat (die Details weiss ich leider nicht mehr, bin mir aber recht sicher, dass das gehen wuerde).
Insgesamt ergibt sich, dass __gen_tempname (und somit mkstemp(3), mktemp(1), und mehr noch mktemp(3)) nicht wirklich "sicher" sind, auch wenn diese Sicherheit wohl fuer die meisten Faelle in der Praxis ausreicht.
Ich sehe das Problem darin, daß jeder in tmp schreiben darf. Dann wäre es doch besser, wenn /tmp root gehört mit den Rechten 755 und für jeden User gibt es ein eigenes Unterverzeichnis, daß ihm gehört, und wo er hineinschreiben darf. Das wäre dann eine vernünftige Lösung. Wie sollte man dann sonst eine Interprozeßkommunikation, über verschiedene Prozesse hinweg, mittels Dateien gestalten? Da müssen doch beide Prozesse wissen, wie der Dateiname heißt.
Kurz und gut: Die Sicherheit von __gen_tempname (und abegeleitete) beruht auf der Vorhersagbarkeit von __gettimeofday(), und die _ist_ vorherzusagen...
Wenn du das mit den Kommentaren am Anfang von /usr/src/linux/drivers/char/random.c vergleichst, insbesondere, welche wesentlich zufaelligeren Datenquellen im Vergleich zu __gettimeofday verwendet werden, wirst du sehen, dass das _vergleichsweise_ unsicher ist (auch wenn es fuer die meisten _praktischen_ Faelle ausreichen sollte.
Ein "sicheres" __gen_tempname wuerde also nicht 64 bit aus __gettimeofday + PID sondern 64 bit aus /dev/random verwenden,
ACK
das u.a. Tastatur(Taste, Zeitpunkt), Maus (Position, Klicks, Zeitpunkt), HD (Zeit von IO ops), IRQs (Zeitpunkt) allgemein verwendet und mit (wenn nicht) der beste Zufallsgenerator auf PCs ist.
Und nur, damit keine Missverstaendnisse aufkommen: Fuer (fast) alle praktischen Anwendungen ist __gen_tempname (also auch mkstemp und mktemp) sicher genug! Und auch die zeitliche Aufloesung von __gettimeofday sollte fuer (fast) alle Anwendungen "reichen" um zusaetzliche Sicherheit zu gewaehrleisten.
Leider bin ich weder in C noch in der Kryptographie bewandert genung um auch nur eine Abschaetzung der Sicherheit (d.h. des Aufwandes, um z.B. oben skizzierten Angriff durchzufuehren) zu wagen...
Um nochmal zusammenzufassen:
Die (pauschale(!!!)) Aussage __gen_tempname (und somit mkstemp(3) und somit mktemp(1)) sei "sicher" ist falsch!
Die Aussage __gen_tempname sei sicher _genug_ fuer *fast* alle Anwendungen ist IMO richtig!
Und nochmal: Die "Eindeutigkeit" des erzeugten Muster ist mit 62^6 IMO gut genug, die "Schwaeche" ist die Vorhersagbarkeit des Ergebnisses (egal in welcher Stufe, sei's noch innerhalb von __gen_tempname, sei's in mkstemp(3) oder sei's in mktemp(1)).
Die "Guete" von 62^6 ist aber nur gleichzusetzen mit einer "Schluessel- laenge" x von 35 bit < x < 36 Bit... Und das ist heutzutage kein Problem.
Doch, denn Du hast nur ein paar Nanosekunden Zeit, wenn ich es richtig sehe.
Und da gettimeofday quasi fuer jeden beliebigen Zeitpunkt im Voraus(!)[3] berechnet werden kann (und die PID ein "piece of cake" ist)...
Hmm. Sowenig das ganze mit der Praxis zu tun haben mag (das kann und will ich nicht beurteilen, ich bin kein Hacker und erst recht kein Cracker), so hoffe ich doch, das "blinde" Vertrauen erschuettert zu haben und, wie Wolfgang es bei mir in Sachen Race-Conditions etc. generell tat, auch bei dir (und anderen?) ein gewisses, gesundes Misstrauen und vielleicht auch Interesse an der Problematik geweckt zu haben.
Ja, klar fuer die 08/15 Kiste ist sogar mktemp vielleicht schon overkill, aber fuer Rechner, die sicher sein muessen, ist IMO eine bessere Version von mkstemp (s.o., mit /dev/random) zu verwenden...
Und ja, auf solchen Kisten, sollte man wohl die GNU libc sowieso nicht verwenden ;)
-dnh
P.S: Ja, das "clever" in __gen_tempname hat mich stutzig gemacht...
PPS: Nein, ich bin kein Sicherheitsfetischist, ich hab weder eine Firewall am laufen noch einen aktuellen PGP/GPG Key...
Dann schreib es nicht auch noch in einer öffentlichen Liste. ;) Bernd -- Homepages von deutschsprachigen Linux-Gurus: Kristian Köhntopp: http://www.koehntopp.de/kris/artikel/ Sven Guckes: http://www.math.fu-berlin.de/~guckes/sven Robin S Socha: http://socha.net/index2.html |Zufallssignatur 10
On Don, 19 Jul 2001 at 14:47 (+0200), Bernd Brodesser wrote:
* David Haller schrieb am 19.Jul.2001: [...]
Cannot create temp file /root/test.YTRUBd: Permission denied
Wenn das so manchen User vorgelegt wird, dann weigert er sich noch weiter an diesem Rechner zu arbeiten, bis ein Geisterbeschwörer die Tastatur und den Bildschirm ausgependelt hat und bestätigt hat, daß eine weitere Benutzung des Rechners nicht notwendig einen Weltkrieg auslöst. "Was soll YTRUBd sein, und wie ließt man das?"
*LOL* [mktemp prüft die Existenz der Datei nicht]
Dann ist das aber ein Gewaltiger Rückschritt. Wenn ich mich Recht erinnere und nicht völlig daneben liege, hat das eine HP_UX-Kiste genau so gemacht. Hatte ich mal durchgetestet. Da hat er Anstelle von a$$ eben b$$ geschrieben.
Na, so gewaltig ist der Rückschritt ja nun auch nicht. Das sind ein paar Zeilen Shell-Code und dann hast Du diese Funktionalität. Man muss es eben nur wissen. Es hat auch einen Vorteil: Man kann selbst bestimmen, wie oft er das Spielchen machen soll. [Sicherheit des mktemp]
Ich sehe das Problem darin, daß jeder in tmp schreiben darf. Dann wäre es doch besser, wenn /tmp root gehört mit den Rechten 755 und für jeden User gibt es ein eigenes Unterverzeichnis, daß ihm gehört, und wo er hineinschreiben darf. Das wäre dann eine vernünftige Lösung. Wie sollte man dann sonst eine Interprozeßkommunikation, über verschiedene Prozesse hinweg, mittels Dateien gestalten? Da müssen doch beide Prozesse wissen, wie der Dateiname heißt.
IPC mittels Dateien? Wo hast Du _das_ denn schon mal gesehen (mal abgesehen von einem PID-File, das liegt aber in der Regel in /var/run, nicht /tmp). Dafür nimmt man Pipes, Semaphore, Signale oder Shared Memory. Jan
On Mit, 18 Jul 2001 at 23:34 (+0200), David Haller wrote:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [...]
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Naja, so viele Fälle gibt es ja wohl nicht und es ist für den Anwender nicht primär entscheidend zu wissen, was denn nun genau schief gelaufen ist (wenn er Ahnung hat, kann er mittels df, ls und so weiter selbst auf Fehlersuche gehen, wenn nicht, dann nützen ihm genauere Meldungen auch nichts). Wichtig ist vorrangig, zu entscheiden ob das Programm weitermachen kann. Das kann man einfach so klären, dass in einer Schleife n-mal versucht wird, eine temp. Datei anzulegen und dann erst aufgegeben wird (wobei n nicht zu hoch sein sollte - vielleicht 5 - 10). Wenn man es ganz sauber macht, dann prüft man im Fehlerfall ein paar Sachen ab (habe ich Schreibrechte im Verzeichnis, ist das FS voll?), in denen ein nochmaliges Probieren sinnlos wäre und versucht es dann einfach ein paar Mal. So kann man evtl. Namensgleichheiten abfangen. [...]
Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen.
Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits") zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler- ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
Es ist schade, dass der Patch das tut. Kennst du einen Grund dafür?
Dann schlage ich sowas wie
${prg}.`date +%s`.$$.tmp vor. Da gibt es so schnell keine doppelte, es sei denn es werden im Prozeß selber mehere tmp angelegt. Die kann ich dann aber hart anders nennen, etwa:
$TMP1=$TMPDIR/$PRG.A`date +%s`.$$.tmp $TMP2=$TMPDIR/$PRG.B`date +%s`.$$.tmp $TMP3=$TMPDIR/$PRG.C`date +%s`.$$.tmp
Sollte man in einer Schleife Tempdateien anlegen (könnte ja sein, daß man das braucht. ;)) dann wird der Schleifenzähler mit im Namen aufgeführt.
Ack.
Das ist genauso unsicher wie eine von mktemp erzeugte Version (in die man per Vorlage ja auch $$ und $prg einfließen lassen kann). Man kann sich nie 100% sicher sein, dass das Anlegen der temp. Datei klappt und muss in jedem Fall einen potenziellen Fehler abfangen. Jan
* Jan Trippler schrieb am 19.Jul.2001:
On Mit, 18 Jul 2001 at 23:34 (+0200), David Haller wrote:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [...]
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Naja, so viele Fälle gibt es ja wohl nicht und es ist für den
Richtig, daß meiste träte doch schon bei den ersten Versuchen auf, und der Programmierer programierte es einfach um, vergäbe Recht usw. Nur das mit der Disk voll kann man nicht richtig überprüfen. Selbst wenn man die Disk künstlich randvoll macht, weiß man nicht ob es genau zu einem bestimmten Zeitpunkt vollläuft. Trotzdem kann es sein, daß auch später mal die Rechte nicht stimmen oder so.
Anwender nicht primär entscheidend zu wissen, was denn nun genau schief gelaufen ist (wenn er Ahnung hat, kann er mittels df, ls und so weiter selbst auf Fehlersuche gehen, wenn nicht, dann nützen ihm genauere Meldungen auch nichts). Wichtig ist vorrangig, zu entscheiden ob das Programm weitermachen kann. Das kann man einfach so klären, dass in einer Schleife n-mal versucht wird, eine temp. Datei anzulegen und dann erst aufgegeben wird (wobei n nicht zu hoch sein sollte - vielleicht 5 - 10). Wenn man es ganz sauber macht, dann prüft man im Fehlerfall ein paar Sachen ab (habe ich Schreibrechte im Verzeichnis, ist das FS voll?), in denen ein nochmaliges Probieren sinnlos wäre und versucht es dann einfach ein paar Mal. So kann man evtl. Namensgleichheiten abfangen.
ACK.
Dann schlage ich sowas wie
${prg}.`date +%s`.$$.tmp vor. Da gibt es so schnell keine doppelte, es sei denn es werden im Prozeß selber mehere tmp angelegt. Die kann ich dann aber hart anders nennen, etwa:
$TMP1=$TMPDIR/$PRG.A`date +%s`.$$.tmp $TMP2=$TMPDIR/$PRG.B`date +%s`.$$.tmp $TMP3=$TMPDIR/$PRG.C`date +%s`.$$.tmp
Sollte man in einer Schleife Tempdateien anlegen (könnte ja sein, daß man das braucht. ;)) dann wird der Schleifenzähler mit im Namen aufgeführt.
Ack.
Das ist genauso unsicher wie eine von mktemp erzeugte Version (in die man per Vorlage ja auch $$ und $prg einfließen lassen kann).
Nun, wie soll zur gleichen Sekunde die gleiche PID meines Skripts nochmal verwendet werden? Außer mein Skript macht es selber, aber dazu habe ich ja schon was geschrieben. Nun ja, vielleicht wenn die Uhr mal total falsch geht, oder wenn die Prozeßtabelle fast voll ist, aber dann ist das System sowieso schon hinüber.
Man kann sich nie 100% sicher sein, dass das Anlegen der temp. Datei klappt und muss in jedem Fall einen potenziellen Fehler abfangen.
ACK Bernd -- Welches Buch ist zu empfehlen? Schon mal bei SuSE vorbeigesehen? http://www.suse.de/de/produkte/buecher/index.html oder die Empfehlungen der SuSE-Entwickler auf dem eigenen Rechner? file:///usr/shar/doc/sdb/de/html/literatur.html |Zufallssignatur 5
On Don, 19 Jul 2001 at 12:13 (+0200), Bernd Brodesser wrote:
* Jan Trippler schrieb am 19.Jul.2001: [Dateien mit Zeitstempel usw. erzeugen]
Das ist genauso unsicher wie eine von mktemp erzeugte Version (in die man per Vorlage ja auch $$ und $prg einfließen lassen kann).
Nun, wie soll zur gleichen Sekunde die gleiche PID meines Skripts nochmal verwendet werden? Außer mein Skript macht es selber, aber dazu habe ich ja schon was geschrieben. Nun ja, vielleicht wenn die Uhr mal total falsch geht, oder wenn die Prozeßtabelle fast voll ist, aber dann ist das System sowieso schon hinüber.
Oder ein anderes Script nutzt die gleichen Bezeichnungen (es kann ja mehrere Scripte / Programme mit gleichem Namen im System geben), oder ein anderes Script nutzt die gleichen Bezeichnungen hart kodiert oder ein anderes Programm baut temp. Namen nach einem völlig anderen Prinzip auf, die zufälligerweise genau das gleiche Ergebnis bringen, ... Es steht doch nirgends, dass da an Stelle x - y im Dateinamen die PID liegt. Das kann irgendeine Zahl sein (ein Prozess könnte ja auch an diesen Stellen sein Alter in ms einbauen). Du müsstest schon erzwingen, dass alle Programme den gleichen Mechanismus nutzen und das ist illusorisch. In allen Fällen ist es egal, wie ich den temp. Namen aufbaue - egal ob über irgendwelche Operationen aus der Systemzeit wie mktemp oder wie Du aus Programmnamen, Prozess-ID und Zeitstempel - die Wahrscheinlichkeit, dass ein anderer Prozess eine gleich benannte Datei nutzt ist zwar verschwindend gering, aber nicht Null. Jan
On Don, 19 Jul 2001, Jan Trippler wrote:
On Mit, 18 Jul 2001 at 23:34 (+0200), David Haller wrote:
On Mit, 18 Jul 2001, Bernd Brodesser wrote:
* David Haller schrieb am 18.Jul.2001: [...]
$ mktemp /root/${prg}.$$.XXXXXX Cannot create temp file /root/.12760.YTRUBd
Ich mache meine Fehlermeldung lieber selber. Was soll der Endanwender mit obiger Meldung anfangen?
Du weisst ja auch nix genaues (Rechte, Disk voll, uebergeordnetes Verz. existiert nicht)... Du weisst du dass es nicht geklappt hat (mkstemp liefert nur 1 als exit-status).
Naja, so viele Fälle gibt es ja wohl nicht und es ist für den Anwender nicht primär entscheidend zu wissen, was denn nun genau schief gelaufen ist (wenn er Ahnung hat, kann er mittels df, ls und so weiter selbst auf Fehlersuche gehen, wenn nicht, dann nützen ihm genauere Meldungen auch nichts). Wichtig ist vorrangig, zu entscheiden ob das Programm weitermachen kann.
Hmja, _mich_ wuerde es auch als Anwender interessieren, ob's z.B. an den Permissions oder am Plattenplatz lag... (EPERM/ENOSPC)...
Das kann man einfach so klären, dass in einer Schleife n-mal versucht wird, eine temp. Datei anzulegen und dann erst aufgegeben wird (wobei n nicht zu hoch sein sollte - vielleicht 5 - 10). Wenn man es ganz sauber macht, dann prüft man im Fehlerfall ein paar Sachen ab (habe ich Schreibrechte im Verzeichnis, ist das FS voll?), in denen ein nochmaliges Probieren sinnlos wäre und versucht es dann einfach ein paar Mal. So kann man evtl. Namensgleichheiten abfangen.
ACK.
[...]
Wichtig ist doch, daß mktemp überprüft, ob der vorgeschlagene Dateiname schon existiert oder nicht. Wenn es das nicht tut, dann ist es nicht zu gebrauchen.
Tut es. Es scheitert dann (bzw. mkstemp(3) scheitert und gibt in errno EEXIST ("File exists" bzw. "Die Datei existiert bereits") zurueck. Leider gibt die gepatchte Version von mktemp diese Fehler- ursachen weder aus noch weiter (z.B. mittels 'exit(errno);')...
Es ist schade, dass der Patch das tut. Kennst du einen Grund dafür?
Nein. Ich bin auch erst im Zusammenhang mit diesem Thread darueber gestolpert... Was mich ein wenig wundert, ist, dass der patch evtl. von DJB ist... --- mktemp-1.4/Makefile.djb Tue Sep 16 14:59:57 1997 +++ mktemp-1.4/Makefile Tue Sep 16 15:04:56 1997 Oder ist das (in diesem Fall in dieser Hinsicht bessere) Original von DJB? Hm. Glaub's fast... Ich bezieh mich hier auf den mktemp-1.5-linux.patch der beim mktemp-1.5 von kernel.org im src.rpm steckt... Und scheinbar ist auch in meinem mktemp der SuSE 6.2: '$ rpm -qf `which mktemp`\nmktemp-1.4-66' der oder ein aehnlicher patch drin... Jedenfalls gibt mein mktemp hier kein "Permission denied" aus (wie das Original via err() aus err.h).
Das ist genauso unsicher wie eine von mktemp erzeugte Version (in die man per Vorlage ja auch $$ und $prg einfließen lassen kann).
Ja, stimmt, tempfile="`mktemp ${prg}-\`date "+%s"\`-$$.XXXXXX`" duerfte das beste sein ;) Siehe aber auch meine Antwort zu Bernds mail...
Man kann sich nie 100% sicher sein, dass das Anlegen der temp. Datei klappt und muss in jedem Fall einen potenziellen Fehler abfangen.
Ja. Das ist "vorgefertigt" glaub nicht zu haben. Und IMO waere da eine Rueckgabe von errno (via exit(errno) aus mktemp) ganz praktisch. -dnh -- 8: Globale Variable Der Aktienkurs von Netscape. (Kristian Köhntopp)
On Don, 19 Jul 2001 at 12:22 (+0200), David Haller wrote: [...]
Hmja, _mich_ wuerde es auch als Anwender interessieren, ob's z.B. an den Permissions oder am Plattenplatz lag... (EPERM/ENOSPC)...
Jepp, aber wie gesagt: Das kannst Du auch selber prüfen. Wäre natürlich schön, wenn mktemp es liefern würde, aber da sind wir uns glaube ich einig. [...]
Ja, stimmt, tempfile="`mktemp ${prg}-\`date "+%s"\`-$$.XXXXXX`" duerfte das beste sein ;)
Interessant, das das funktioniert ;-) tempfile="`mktemp ${prg}-\`date "+%s"\`-$$.XXXXXX`" ^^^^^ an der Stelle hätte ich einen Fehler vermutet, aber offenbar haben die Backticks eine höhere Priorität als die "". Jan
Hallo Heinz, * Am 15.07.2001 um 22:45 Uhr schrieb Heinz W. Pahlke:
beizubringen. Also muss ich wohl doch losziehen, mir mal ein vernuenftiges Buch zur Shellprogrammierung zu kaufen. Das, was ich habe, ist doch nicht so doll, und auf dem Bildschirm lese ich laengere Texte nur sehr ungern.
hier ein paar brauchbare Quellen zur Shellprogrammierung: UNIX Shellprogrammierung http://www.koehntopp.de/kris/artikel/unix/shellprogrammierung/ Heiner's SHELLdorado http://www.oase-shareware.org/shell/ Sams Teach Yourself Shell Programming in 24 Hours http://infobase.informit.com/linux/content/0672314819/index.htm Jürgen -- Je größer das Programmiervorhaben, um so spaeter werden grundlegende Ablauf-Fehler entdeckt. / Registered Linux-User #130804 http://counter.li.org \ \ Linux Stammtisch Bremerhaven http://linux.hs-bremerhaven.de /
Am Dienstag 17 Juli 2001 08:11 schrieben Sie:
Hallo Heinz,
* Am 15.07.2001 um 22:45 Uhr schrieb Heinz W. Pahlke:
beizubringen. Also muss ich wohl doch losziehen, mir mal ein vernuenftiges Buch zur Shellprogrammierung zu kaufen. Das, was ich habe, ist doch nicht so doll, und auf dem Bildschirm lese ich laengere Texte nur sehr ungern.
hier ein paar brauchbare Quellen zur Shellprogrammierung:
UNIX Shellprogrammierung http://www.koehntopp.de/kris/artikel/unix/shellprogrammierung/
Heiner's SHELLdorado http://www.oase-shareware.org/shell/
Sams Teach Yourself Shell Programming in 24 Hours http://infobase.informit.com/linux/content/0672314819/index.htm
Jürgen
hallo, in Sachen Literatur zur Shell - Programmierung kann auch sehr das Buch "Linux in a nutshell" von http://www.oreilly.com/catalog/linuxnut3/ empfehlen. mfg Andre andre.ac.pfeiler@uunet.de nail@ndo.ath.cx
On 17-Jul-2001 Andre P. wrote:
in Sachen Literatur zur Shell - Programmierung kann auch sehr das Buch "Linux in a nutshell" von http://www.oreilly.com/catalog/linuxnut3/ empfehlen.
Ist zum Nachschlagen wirklich hervorragend, aber lernen laesst es sich
danach nur sehr schwer. Zumindest sollte man IMHO doch schon ueber mehr
als nur einige Grundkenntnisse verfuegen.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
On Tuesday 17 July 2001 11:34, you wrote:
On 17-Jul-2001 Andre P. wrote:
in Sachen Literatur zur Shell - Programmierung kann auch sehr das Buch "Linux in a nutshell" von http://www.oreilly.com/catalog/linuxnut3/ empfehlen.
Ist zum Nachschlagen wirklich hervorragend, aber lernen laesst es sich danach nur sehr schwer. Zumindest sollte man IMHO doch schon ueber mehr als nur einige Grundkenntnisse verfuegen.
Beste Gruesse,
Heinz.
Jo, dass stimmt, aber es ist ein guter Anfang , muss man einfach haben denke ich. ...kann man immer mal gebrauchen. greets Andre
Hallo Juergen, On 17-Jul-2001 Juergen Schwarting wrote:
hier ein paar brauchbare Quellen zur Shellprogrammierung:
UNIX Shellprogrammierung http://www.koehntopp.de/kris/artikel/unix/shellprogrammierung/
Kenne ich, aber hilft mir nicht sehr viel weiter, weil Sachen wie while read i; do if test -z "$i"; then ... nicht erklaert sind, also wie z.B. das "i" zustandekommt.
Heiner's SHELLdorado http://www.oase-shareware.org/shell/
Sams Teach Yourself Shell Programming in 24 Hours http://infobase.informit.com/linux/content/0672314819/index.htm
Die kannte ich noch nicht. Sind aber leider in Englisch, mit dem ich
mich reichlich schwer tue.
Trotzdem vielen Dank,
Heinz.
--
E-Mail: Heinz W. Pahlke
* Heinz W. Pahlke schrieb am 17.Jul.2001:
Kenne ich, aber hilft mir nicht sehr viel weiter, weil Sachen wie
while read i; do if test -z "$i"; then ...
nicht erklaert sind, also wie z.B. das "i" zustandekommt.
Ist ein beliebiger Name. Kannst Du auch was anders für nehmen. Bernd -- ROTFL = Rolling On The Floor, Laughing = Auf dem Boden wälzen, lachend. SCNR = Sorry, Could Not Resist = Sorry, Ich konte nicht wiederstehen. AFAIK = As Far As I Know = So weit ich weis|BTW = By The Way = Nebenbei bemerkt IMHO = In My Humble Opinion = meiner bescheidenen Meinung nach |Zufallssig. 9
Hallo, On Tue, 17 Jul 2001 at 12:52 (+0200), Bernd Brodeßer wrote:
* Heinz W. Pahlke schrieb am 17.Jul.2001:
Kenne ich, aber hilft mir nicht sehr viel weiter, weil Sachen wie
while read i; do if test -z "$i"; then ...
nicht erklaert sind, also wie z.B. das "i" zustandekommt.
Ist ein beliebiger Name. Kannst Du auch was anders für nehmen.
Schon klar. Nur würde mich mal interessieren, wie dieses "i" zustande kommt. Verwendet man ja auch gerne in For-Schleifen (C(++)/Java/Perl) als Zähler. Ich vermute mal, dass das was mit Mathe zu tun hat, wo man i oft als Index verwendet (x_{i+1} = x_i - \frac{f(x_i)}{f'(x_i)} um mal eine Formel zu nennen). Bleibt die Frage: woher kommt das i. Gruß, Bernhard -- First they ignore you Then they laugh at you Then they fight you Then you win ! -- Mahatma Ghandi
On Die, 17 Jul 2001 at 14:13 (+0200), Bernhard Walle wrote:
On Tue, 17 Jul 2001 at 12:52 (+0200), Bernd Brodeßer wrote:
* Heinz W. Pahlke schrieb am 17.Jul.2001:
Kenne ich, aber hilft mir nicht sehr viel weiter, weil Sachen wie
while read i; do if test -z "$i"; then ...
nicht erklaert sind, also wie z.B. das "i" zustandekommt.
Ist ein beliebiger Name. Kannst Du auch was anders für nehmen.
Schon klar. Nur würde mich mal interessieren, wie dieses "i" zustande kommt. Verwendet man ja auch gerne in For-Schleifen (C(++)/Java/Perl) als Zähler.
Ich vermute mal, dass das was mit Mathe zu tun hat, wo man i oft als Index verwendet (x_{i+1} = x_i - \frac{f(x_i)}{f'(x_i)} um mal eine Formel zu nennen). Bleibt die Frage: woher kommt das i.
Aus dem Alphabet. Man muss es zwischen h und j rauszerren, dann hat man eins ;-) Ich vermute mal, dass das entweder (wie Du schon geschrieben hast), von *Index* kommt oder aber von *Inkrement* - aber eigentlich ist es doch egal, oder? Jan
Hello Jan, Tuesday, July 17, 2001, 4:40:05 PM, Jan Trippler wrote:
Aus dem Alphabet. Man muss es zwischen h und j rauszerren, dann hat man eins ;-) Ich vermute mal, dass das entweder (wie Du schon geschrieben hast), von *Index* kommt oder aber von *Inkrement* - aber eigentlich ist es doch egal, oder? Ist es. Aber ich habe da auch noch ein bisschen "Senf" dazu. In FORTRAN (kennt vielleicht der eine oder andere) werden Variablen, die mit i,j,k,l,m,n begannen, vom Compiler automatisch als Integer erkannt. Und Schleifenvariablen sind ganzzahlige Werte. Das ist halt so. In FORTRAN, in den SHELLS, in PERL ....... Ein bisschen Philosophie morgens, vor dem Alltag, im Büro..... -- Best regards, Roland mailto:roland.suehsmuth@boecker-online.de
Jan Trippler wrote:
On Die, 17 Jul 2001 at 14:13 (+0200), Bernhard Walle wrote:
On Tue, 17 Jul 2001 at 12:52 (+0200), Bernd Brodeßer wrote:
* Heinz W. Pahlke schrieb am 17.Jul.2001:
Kenne ich, aber hilft mir nicht sehr viel weiter, weil Sachen wie
while read i; do if test -z "$i"; then ...
nicht erklaert sind, also wie z.B. das "i" zustandekommt.
Ist ein beliebiger Name. Kannst Du auch was anders für nehmen.
Schon klar. Nur würde mich mal interessieren, wie dieses "i" zustande kommt. Verwendet man ja auch gerne in For-Schleifen (C(++)/Java/Perl) als Zähler.
Ich vermute mal, dass das was mit Mathe zu tun hat, wo man i oft als Index verwendet (x_{i+1} = x_i - \frac{f(x_i)}{f'(x_i)} um mal eine Formel zu nennen). Bleibt die Frage: woher kommt das i.
Aus dem Alphabet. Man muss es zwischen h und j rauszerren, dann hat man eins ;-)
Ich vermute mal, dass das entweder (wie Du schon geschrieben hast), von *Index* kommt oder aber von *Inkrement* - aber eigentlich ist es doch egal, oder?
Hi, ich nehme dafuer immer inp, fuer input. Ich neige also dazu das i als synonym fuer input zu verstehen ;) Ich kann mir denken, dass das verwirrende an dem Konstrukt, die Art der Wertzuweisung ist. Normalerweise heisst es ja: i=`command`. Dass read als Argument einen (oder mehrere) Variablenbezeichner erhaelt und darin das Ergebnis liefert, ist in der Shell eher ungewoehnlich. Im Moment faellt mir kein anderes Shellkommando ein, das auch so funktioniert. read kann aber auch nur so funktionieren, weil die Shell a b c d=`read` mit einem Fehler quittieren wuerde. so long... bernd
Hallo, On Sun, 15 Jul 2001 at 22:45 (+0200), Heinz W. Pahlke wrote:
Aber ich sehe ein, dass diese Liste nicht dazu da ist, mir die bash beizubringen. Also muss ich wohl doch losziehen, mir mal ein vernuenftiges Buch zur Shellprogrammierung zu kaufen. Das, was ich habe, ist doch nicht so doll, und auf dem Bildschirm lese ich laengere Texte nur sehr ungern.
Vielleicht eine Buchempfehlung: "Jetzt lerne ich Shellprogrammierung", Markt&Technik, M. Rathmann, C. Wieskotten, ISBN 3-3272-5551-1, 49.95 DEM / 365.00 ATS Gruß, Bernhard -- Gefällt der Ausdruck von Mutt nicht? Muttprint verschönert ihn. http://home.t-online.de/~f.walle/muttprint/"
Hallo Heinz, On Sun, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote:
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_ will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Vermutlich ist es ja wieder sehr einfach, wenn man es weiss ;-)
Also ich habe mal gelesen, dass sed zeilenorientiert arbeitet und dies nicht möglich sei. Mit Perl geht's aber perl -pe 's/\n//g' test.txt Wichtig ist, dass nicht das Zeilenende ersetzt werden soll (das ändert gar nichts) sondern dass Newlines entfernt werden soll. Auch wichtig ist, dass die Regexp in '' stehen soll, damit die Shell nicht "Vorarbeit" leistet. HTH Gruß, Bernhard -- "The most reliable proof that there are extraterrestrial intelligent lifeforms out there is that nobody actually tries to get in contact with us. [Dirk Müller, KDE-Entwickler]
On 15-Jul-2001 Bernhard Walle wrote:
On Sun, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote:
will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Vermutlich ist es ja wieder sehr einfach, wenn man es weiss ;-)
Also ich habe mal gelesen, dass sed zeilenorientiert arbeitet und dies nicht möglich sei. Mit Perl geht's aber
perl -pe 's/\n//g' test.txt
Dummerweise habe ich mich mit Perl noch nie beschaeftigt. Ansonsten gilt fuer den Ansatz das gleiche wie fuer den Vorschlag von Jan, dass damit auch die Absaetze verschwinden :-(
Wichtig ist, dass nicht das Zeilenende ersetzt werden soll (das
Kein Wunder, dass meine gestrige Suche in meinem Mail- und Newsarchiv wenig erfolgreich war, wenn ich den verkehrten Suchbegriff verwende :-(
ändert gar nichts) sondern dass Newlines entfernt werden soll. Auch wichtig ist, dass die Regexp in '' stehen soll, damit die Shell nicht "Vorarbeit" leistet.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
On Sun, 15 Jul 2001 at 12:09 (+0200), Heinz W. Pahlke wrote:
On 15-Jul-2001 Bernhard Walle wrote:
On Sun, 15 Jul 2001 at 01:08 (+0200), Heinz W. Pahlke wrote:
will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Vermutlich ist es ja wieder sehr einfach, wenn man es weiss ;-)
Also ich habe mal gelesen, dass sed zeilenorientiert arbeitet und dies nicht möglich sei. Mit Perl geht's aber
perl -pe 's/\n//g' test.txt
Dummerweise habe ich mich mit Perl noch nie beschaeftigt.
Ansonsten gilt fuer den Ansatz das gleiche wie fuer den Vorschlag von Jan, dass damit auch die Absaetze verschwinden :-(
Was willst Du überhaupt machen? Vielleicht solltest Du Dich mit "fmt" beschäftigen. man fmt. Probier doch mal folgendes: perl -pne 's/\n//g unless /^$/' test.txt Damit werden Leerzeilen von der Ersetzungsaktion ausgenommen und verschwinden nicht. Evtl. willst Du auch das haben: perl -pne 'if (/^$/) { s/\n/\n\n/; } else { s/\n//; }' text.txt Letztere Zeile wäre übrigens äquivaltent zu folgendem Skript: #!/usr/bin/perl while (<>) { if (/^$/) { s/\n/\n\n/; } else { s/\n//; } } Das ist dann leichter lesbar. Der Parameter 'n' beim Aufruf legt die Schleife schon an. Das Skript / der Aufruf funktioniert auch über eine Pipe (das ist das besondere an <>). Vielleicht ist Perl nicht die beste = kompakteste Lösung für sowas, aber mit awk kenne ich mich nicht so aus und mit sed auch nicht besonders ;-) Gruß, Bernhard -- "And when I don't know of a bug, it doesn't exist." [Linus Torvalds]
Heinz W. Pahlke schrieb am Sonntag den 15. Juli 2001:
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_ will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
IMHO geht das mit sed nicht. perl geht, wäre aber vielleicht etwas übertrieben ;) tr ist Dein Freund. tr -d "\n" Gruß Jens -- .. may the Tux be with you! #130250
Hallo, * Heinz W. Pahlke schrieb am 15.Jul.2001:
Thema ist immer noch sed. Inzwischen macht sed weitgehend das, was _ich_ will. Nur wie schaffe ich es, Zeilenenden zu loeschen?
Gegeben ist ein Text wie:
"Dieser kurze Satz ist ein ziemlich blo edsinniger Satz."
Mit "sed s/$//g" (und verschiedenen Varianten) habe ich es jedenfalls nicht geschafft.
Vermutlich ist es ja wieder sehr einfach, wenn man es weiss ;-)
Ich bin mir sicher, daß es auch einfacher geht, etwa mit awk, aber eine relativ kurze Lösung habe ich auch: cat txt | tr '\n' §|sed 's/§§/¸/g'|sed 's/§/ /g'|tr ¸ '\n' Wobei anstelle von § und ¸ auch irgendetwas anderes genommen werden kann, was nicht im Text auftaucht. Bernd -- Was ist quoten? Quoten ist das Zitieren aus einer mail, der man antwortet. Und wie macht man es richtig? Zitate werden mit "> " gekennzeichnet. Nicht mehr als nötig zitieren. Vor den Abschnitten das Zitat, auf das man sich bezieht, mit einer Zeile Abstand oben und unten. |Zufallssignatur 12
On 18-Jul-2001 Bernd Brodesser wrote:
Ich bin mir sicher, daß es auch einfacher geht, etwa mit awk, aber
Von dem ich aber bisher ueberhaupt keine Ahnung habe :-(
eine relativ kurze Lösung habe ich auch:
cat txt | tr '\n' §|sed 's/§§/¸/g'|sed 's/§/ /g'|tr ¸ '\n'
Danke. Ich werde wohl auch noch einiges andere mit tr anstatt sed
erledigen, denn inzwischen braucht mein Script fuer einie 1000 Byte
doch schon einige Sekunden, und das nervt ;-) tr schreibt ja wohl
direkt in die Datei, waere fuer sed immer eine temporaere Datei noetig
ist.
Beste Gruesse,
Heinz.
--
E-Mail: Heinz W. Pahlke
* Heinz W. Pahlke schrieb am 18.Jul.2001:
On 18-Jul-2001 Bernd Brodesser wrote:
Ich bin mir sicher, daß es auch einfacher geht, etwa mit awk, aber
Von dem ich aber bisher ueberhaupt keine Ahnung habe :-(
Laß es bleiben. Lern perl, damit ist alles einfacher.
eine relativ kurze Lösung habe ich auch:
cat txt | tr '\n' §|sed 's/§§/¸/g'|sed 's/§/ /g'|tr ¸ '\n'
Danke. Ich werde wohl auch noch einiges andere mit tr anstatt sed erledigen, denn inzwischen braucht mein Script fuer einie 1000 Byte doch schon einige Sekunden, und das nervt ;-) tr schreibt ja wohl direkt in die Datei, waere fuer sed immer eine temporaere Datei noetig ist.
Nö, siehe meine pipe, da sind auch ein paar sed mit dabei. AFAIR geht es auch nur mit sed ohne temp-Dateien, mit Buffer und so. Allerdings habe ich absolut keine Lust das mir anzueignen, da das zimmlich merkwürdig ist. Der Vorteil von tr ist, daß es das Newline wie ein normales Zeichen behandelt, der Nachteil, daß es nur ein Zeichen durch ein anderes ersetzen kann, nicht aber Zeichenkombinationen. Bernd -- Bitte die Etikette beachten: http://home.t-online.de/~f.walle/etikette.html Bitte Realnamen angeben, kein Vollquoting, kein Html, PGP oder Visitenkarten benutzen. Signatur mit "-- " abtrennen, bei Antworten "Re: " voranstellen, sonst nichts. |Zufallssignatur 4
On Mit, 18 Jul 2001 at 11:40 (+0200), Heinz W. Pahlke wrote:
On 18-Jul-2001 Bernd Brodesser wrote: [...]
cat txt | tr '\n' §|sed 's/§§/¸/g'|sed 's/§/ /g'|tr ¸ '\n'
Danke. Ich werde wohl auch noch einiges andere mit tr anstatt sed erledigen, denn inzwischen braucht mein Script fuer einie 1000 Byte doch schon einige Sekunden, und das nervt ;-) tr schreibt ja wohl direkt in die Datei, waere fuer sed immer eine temporaere Datei noetig ist.
Nö, tr schreibt wie sed auf stdout. Probier mal die Perl-Lösungen, die hier kamen. Jan
participants (12)
-
Andre P.
-
Andre Pfeiler
-
B.Brodesser@t-online.de
-
Bernd Obermayr
-
Bernhard Walle
-
David Haller
-
Heinz W. Pahlke
-
Jan.Trippler@t-online.de
-
Jens Tautenhahn
-
Juergen Schwarting
-
Roland Suehsmuth
-
Stephan Hakuli