Názory k článku
Hrátky z řádky: pomocné soubory a zamykání
marvin (neregistrovaný)
7. 4. 2008 2:50
Nový
lock
celé vlákno
napadlo mi toto:
1.skontrolujeme ci existuje foo-lockfile
2.ak ano->cakame kym sa uvolni zamok
ak nie-> echo $PID >>foo-lockfile
3.skontrolujeme ci cislo na zaciatku foo-lockfile je pid nasho procesu
ak ano-> zamok je nas
ak nie-> cakame kym sa uvolni zamok
to by malo stacit,ak si to dobre pamatam z unixovych cviceni:)
1.skontrolujeme ci existuje foo-lockfile
2.ak ano->cakame kym sa uvolni zamok
ak nie-> echo $PID >>foo-lockfile
3.skontrolujeme ci cislo na zaciatku foo-lockfile je pid nasho procesu
ak ano-> zamok je nas
ak nie-> cakame kym sa uvolni zamok
to by malo stacit,ak si to dobre pamatam z unixovych cviceni:)
uživatel si přál zůstat v anonymitě
7. 4. 2008 3:05
Nový
Re: lock
celé vlákno
to by stacilo, kdyby vsechny programy pristupujici k tomu souboru pouzivaly stejny typ zamykani
peter (neregistrovaný)
7. 4. 2008 9:27
Nový
Re: lock
celé vlákno
a co ked dva konkurencne procesy budu prebiehat takto:
p1: kontrola => subor neexistuje
p2: kontrola => subor neexistuje
p1: echo $PID >> foo-lockfile
p1: kontrola => cislo pid je nase => zamok je nas
p2: echo $PID >> foo-lockfile
p2: kontrola => cislo pid je nase => zamok je nas
p1: kontrola => subor neexistuje
p2: kontrola => subor neexistuje
p1: echo $PID >> foo-lockfile
p1: kontrola => cislo pid je nase => zamok je nas
p2: echo $PID >> foo-lockfile
p2: kontrola => cislo pid je nase => zamok je nas
pht (neregistrovaný)
7. 4. 2008 9:49
Nový
Re: lock
celé vlákno
nebudou, protoze >> a ne >. v poslednim kroku budou v souboru dve pid.
Dan (neregistrovaný)
7. 4. 2008 18:36
Nový
Re: lock
celé vlákno
A co takhle:
p1: kontrola => subor neexistuje
p2: kontrola => subor neexistuje
p1: echo $PID >> foo-lockfile
p2: echo $PID >> foo-lockfile
p1: kontrola => cislo pid neni nase => zamok neni nas
p2: kontrola => cislo pid neni nase => zamok neni nas
Nebo proste situace, kdy p1 nestihne zapsat vse pred tim, nez zacne zapisovat p2 - pak se bude zapisovat na preskacku a pod.
Nic takoveho fungovat nebude...
Jediny zpusob, jak lze efektivne zamykat nejaky proces na nejakem zdroji, je pozadat o to jadro (mutexy semafory,...).
p1: kontrola => subor neexistuje
p2: kontrola => subor neexistuje
p1: echo $PID >> foo-lockfile
p2: echo $PID >> foo-lockfile
p1: kontrola => cislo pid neni nase => zamok neni nas
p2: kontrola => cislo pid neni nase => zamok neni nas
Nebo proste situace, kdy p1 nestihne zapsat vse pred tim, nez zacne zapisovat p2 - pak se bude zapisovat na preskacku a pod.
Nic takoveho fungovat nebude...
Jediny zpusob, jak lze efektivne zamykat nejaky proces na nejakem zdroji, je pozadat o to jadro (mutexy semafory,...).
Ash (neregistrovaný)
7. 4. 2008 23:43
Nový
Re: lock
celé vlákno
Minimálně jeden z procesů p1 p2 si tam to své PID najde (jako první v pořadí v souboru). Takže výsledkem bude "cislo pid je nase" => zamok je nas.
Ondrej (neregistrovaný)
7. 4. 2008 9:56
Nový
Re: lock
celé vlákno
Kez uz robit zamok na fs, tak jedine pomocou mkdir
Pavel (neregistrovaný)
7. 4. 2008 3:45
Nový
lock mkdir
celé vlákno
Vytvoreni adresare je atomicke a selze, pokud existuje. To se da celkem lehce vyuzit.
Proto staci zkouset vytvorit adresar a kontrolovat navratovy kod.
# Zamek
LOCKDIR='/tmp/x'
# Cekani na zamek
while (mkdir $LOCKDIR 2> /dev/null; [ "$?" '!=' 0 ] ); do
sleep 1
done
# Tady jsem sam, dokonce muzu pouzivat $LOCKDIR na sve docasne soubory.
date
# Odstraneni zamku
rm -rf $LOCKDIR
Proto staci zkouset vytvorit adresar a kontrolovat navratovy kod.
# Zamek
LOCKDIR='/tmp/x'
# Cekani na zamek
while (mkdir $LOCKDIR 2> /dev/null; [ "$?" '!=' 0 ] ); do
sleep 1
done
# Tady jsem sam, dokonce muzu pouzivat $LOCKDIR na sve docasne soubory.
date
# Odstraneni zamku
rm -rf $LOCKDIR
matej (neregistrovaný)
7. 4. 2008 10:11
Nový
ln -s lock (was Re: lock mkdir)
celé vlákno
Podobne je atomicke aj vytvorenie linky.
LOCKFILE="/tmp/my.lock"
trap "rm -f $LOCKFILE" EXIT INT TERM
while ! ln -s lock $LOCKFILE; do
echo >&2 "cannot obtain lock, waiting"
sleep 1;
done
# urob co treba atomicky, potom zmaz lock
oldium (neregistrovaný)
7. 4. 2008 13:50
Nový
Re: ln -s lock (was Re: lock mkdir)
celé vlákno
Jedna takova ucelena implementace do Gentoo je v bugu http://bugs.gentoo.org/show_bug.cgi?id=118418. Vicenasobne zamykani pro Bash a zaroven automaticke odemykani pri ukoncovani shellu, dokonce i neco jako threadove promenne. Vse dulezite pro zamky je ve funkci trylock. Snad jedina externi zavislost je na bash_variable z /sbin/functions.sh (pouze Gentoo) pro predelani jmena na neco, co lze uchovat v Bashi. Dale staci nastavit promennou svclock na adresar, kde se ukladaji zamky, a uz muzete zacit pouzivat zamykani.
Zakladni myslenka je v pouziti `set -C; echo "$$ 1" > "$path"`, protoze parametr -C zakaze prepisovani souboru.
Zakladni myslenka je v pouziti `set -C; echo "$$ 1" > "$path"`, protoze parametr -C zakaze prepisovani souboru.
TomEeK (neregistrovaný)
7. 4. 2008 11:39
Nový
Re: lock mkdir
celé vlákno
A nebylo by lepsi misto volani bashe pouzival atomicka volani systemu?
tam by pak o nejakem predbihanim nemelo byt ani reci, ne?
cosi jako v Cecku toto:
char *filename;
int fd;
do {
filename = tempnam (NULL, "foo");
fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
free (filename);
} while (fd == -1);
Jen nevim jak bych to smolil v bashi.
Neporadite?
tam by pak o nejakem predbihanim nemelo byt ani reci, ne?
cosi jako v Cecku toto:
char *filename;
int fd;
do {
filename = tempnam (NULL, "foo");
fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
free (filename);
} while (fd == -1);
Jen nevim jak bych to smolil v bashi.
Neporadite?
pht (neregistrovaný)
7. 4. 2008 6:51
Nový
sleep na retry
celé vlákno
pouzivat konstantni sleep na cekani na nejaky zdroj (napr. zamek) je sebevrazda. obvykle se na to pouziva nejaka dostatecne rychle rostouci posloupnost (napriklad fibonacciho nebo nejaka exponenciela), pripadne nahodna hodnota v nejakem (zvetsujicim se) intervalu. taky je vhodne napriklad po peti neuspesnych pokusech skript ukoncit.
... (neregistrovaný)
7. 4. 2008 7:56
Nový
skvely serial
celé vlákno
vdaka za serial, clovek vzdy najde nieco uzitocne :-) aj po X rokoch pouzivania linuxu
uživatel si přál zůstat v anonymitě
7. 4. 2008 10:27
Nový
Proc tohle nefunguje?
celé vlákno
Mel jsem ted v gentoo problem s odinstalaci texinfo. Mel v prerm zvlastni konstrukci, ktera nefungovala ani, kdyz jsem udelal testovaci soubor. Jde mi o tohle:
#!/bin/bash
function tisk() {
echo -e "line 1\nline 2\nline 3\nline 4"
}
while read nacteno;do echo "precetl $nacteno";done <(tisk)
Po spusteni to zahlasi chybu
./a: line 7: syntax error near unexpected token `<(tisk)' ./a: line 7: `while read nacteno;do echo "precetl $nacteno";done <(tisk)'Pritom ale nasledujici kod probehne v poradku
#!/bin/bash
function tisk() {
echo -e "line 1\nline 2\nline 3\nline 4"
}
cat <(tisk)
Mate nekdo tuseni, proc nefunguje presmerovani stdin do toho read?
7. 4. 2008 10:50
Nový
Re: Proc tohle nefunguje?
celé vlákno
Konstrukce <() funguje v bashi spíše jako makro. spustí podproces a jeho výstup přesměruje do roury a tu rouru předá jako parametr. klíčové slovo done pochopitelně nečeká žádný parametr
$ echo <(echo "ahoj") /dev/fd/63Místo
while read nacteno;do echo "precetl $nacteno";done <(tisk)prostě použij
tisk | while read nacteno;do echo "precetl $nacteno";donea je vymalováno.
uživatel si přál zůstat v anonymitě
7. 4. 2008 11:02
Nový
Re: Proc tohle nefunguje?
celé vlákno
dik za odpoved. Ja osobne pouzivam konstrukce
( prikaz1 ; prikaz2 ; prikaz3 ) | while read .... denne, vcetne zjednodusene formy prikaz | while .....
Tohle byl problem v jinem skriptu, ale privedlo me to na jednu myslenku. Pokud spustim prikaz | while read ... ; do A=neco;done, pak promenna A je zapomenuta a v dalsim kodu ji nepouziju. Tak jsem myslel, ze ten <() by mohl tenhle problem resit. while by se provadelo v aktualnim bashi akorat vstup by byl zmenenej z toho prikazu. Jina moznost me napadla zduplikovat STDIN a pak na stdin presmerovat vystup z toho programu neco jako exec 15<&0 <(tisk), ale tohle se mi taky nejak nepovedlo, stejne tak ani bash -c 'while read .....' <(tisk), coz by ale snad fungovat melo.
Nejakej napad, jak spustit while na vystup z nejakyho programu tak, aby ten while bezel v aktualnim bashi a nespustil podproces a zachovaly se tak nastaveni promennych v aktualnim bashi?
7. 4. 2008 11:34
Nový
Re: Proc tohle nefunguje?
celé vlákno
Na to existuje jediné řešení: Použij sílu (nějaký skutečný programovací jazyk) Luku.
uživatel si přál zůstat v anonymitě
7. 4. 2008 11:39
Nový
Re: Proc tohle nefunguje?
celé vlákno
No, to je odpoved teda docela dost mimo misu:-) Osobne to spis resim tak, ze z toho
prikaz | while ... udelat pomoci echo vystup ve tvaru PROM=VAL a pak davam eval. Ale je to takovy neohrabany, stejne, jako by bylo neohrabany psat 5 radkovy bash skript v nejakym vyssim jazyce.
7. 4. 2008 15:15
Nový
Re: Proc tohle nefunguje?
celé vlákno
Když už se pustíš do
... udelat pomoci echo vystup ve tvaru PROM=VAL a pak davam eval ...tak to už není pětiřádkový bash skript. No a když to nahradím tří řádkovým perl skriptem takový deseti řádkový bash a bez evalů, tak už se to vyplatí.
Ash (neregistrovaný)
7. 4. 2008 23:49
Nový
Re: Proc tohle nefunguje?
celé vlákno
> Tak jsem myslel, ze ten <() by mohl tenhle problem resit.
Ano, konstrukce <() se v bashi skutečně za tím to účelem (zachování proměnných) používá.
Ano, konstrukce <() se v bashi skutečně za tím to účelem (zachování proměnných) používá.
9x0 (neregistrovaný)
7. 4. 2008 21:50
Nový
Re: Proc tohle nefunguje?
celé vlákno
Pokial som to spravne pochopil, tak process substitution ti nahradi <(tisk) v kode za subor, kde sa nachadza vystup funkcie tisk. Budes tam mat teda nieco ako:
while read nacteno;do echo "precetl $nacteno";done /subor
Ty ale chces medzi done a <(tisk) vlozit <, aby si dostal
while read nacteno;do echo "precetl $nacteno";done < /subor
Vid http://tldp.org/LDP/abs/html/process-sub.html - maju tam priklad podobny tvojmu
while read nacteno;do echo "precetl $nacteno";done /subor
Ty ale chces medzi done a <(tisk) vlozit <, aby si dostal
while read nacteno;do echo "precetl $nacteno";done < /subor
Vid http://tldp.org/LDP/abs/html/process-sub.html - maju tam priklad podobny tvojmu
8. 4. 2008 9:23
Nový
Re: Proc tohle nefunguje?
celé vlákno
Nojo, funguje to:
$ function tisk() {
> echo -e "line 1\nline 2\nline 3\nline 4"
> }
$
$ while read nacteno;do echo "precetl $nacteno";done < <(tisk)
precetl line 1
precetl line 2
precetl line 3
precetl line 4
$
Jan Molič (neregistrovaný)
7. 4. 2008 10:46
Nový
flock
celé vlákno
Zkuste použít program "flock". Nahoru do skriptu umistete nasledujici kod, ktery "nahradi sama sebe sama sebou", jen s rozdilem, ze priste nastavi promennoou LOCKED, cimz obejde program flock a pokracuje dal. Pro BSDckare existuje obdobny program "setlock".
#!/bin/bash if [[ -z "$LOCKED" ]] then echo "ceka na zamek" touch ./tmp/lock export LOCKED=1 exec flock ./tmp/lock "$0" "$@" else echo "jedeme dal" fi
PrasopesXXL (neregistrovaný)
7. 4. 2008 16:05
Nový
mktemp v AIXu?
celé vlákno
Zdravim, vi nekdo ekvivalent mktemp pro AIX? Jde o produkcni stroj u zakaznika, takze rady typu "preloz si to pro AIX" nepripadaji v uvahu. Zatim to resim cislem procesu v suffixu, ale zarucene jedinecne jmeno by se mi libilo vice. Diky za kazdou radu!
uživatel si přál zůstat v anonymitě
8. 4. 2008 16:38
Nový
Re: mktemp v AIXu?
celé vlákno
zsh umi napriklad konstrukci =(prikaz), ktera vystup prikazu ulozi do docasneho souboru a vrati jeho nazev. (detailne jsem to nestudoval, ale bezi to pres open s creat|excl, takze je unikatnost zarucena)
still (neregistrovaný)
14. 4. 2008 14:09
Nový
Re: mktemp v AIXu?
celé vlákno
Tiez by ma to zaujimalo :)
JeromeHeretic (neregistrovaný)
7. 4. 2008 23:42
Nový
Takova aprilova blbustka
celé vlákno
Sem kdysi stvoril tuhle kravinku, kdyz je teda zajem o ty shellovy konstrukce:
lynx --source http://www.ucw.cz/~jerome/blbosti/pacman.txt |bash
Vyzaduje bzip2 (asi esencialni v kazdem distru) a uudecode. VRELE DOPORUCUJI spustit v extra terminalu,
jinak je to obtizne killnutelne :-) Neni to zadna veda, ale co si tak pamatuju, tak oescapovat ten zasranej uuencode byla docela pakarna :-)
lynx --source http://www.ucw.cz/~jerome/blbosti/pacman.txt |bash
Vyzaduje bzip2 (asi esencialni v kazdem distru) a uudecode. VRELE DOPORUCUJI spustit v extra terminalu,
jinak je to obtizne killnutelne :-) Neni to zadna veda, ale co si tak pamatuju, tak oescapovat ten zasranej uuencode byla docela pakarna :-)
uživatel si přál zůstat v anonymitě
14. 5. 2008 18:00
Nový
Re: Takova aprilova blbustka
celé vlákno
a jak to souvisi s tematem???
MVA (neregistrovaný)
8. 4. 2008 14:37
Nový
lockfile
celé vlákno
tento problem jsem resil - navic prenositelne - unix,linux, windows(cygwin), ...
nakonec jsem nekde vygoogloval reseniktere udajne pouziva firefox:
jadro problemu je v primititvu, ktera se obvykle teoreticky nazyva TSL (test-and-set lock) - cim ji implementovat na ruznych OS, shellech,atd...
reseni od firefoxaku je vyuzit operaci "mv", ktera z principu sve funkce ASI MELA BYT atomicka - bud se soubor presune nebo to ma skocnit s chybou ("jiz existuje-chcete prepsat?", nema prava, atd...)
takze postup:
lockfile=filelock_xyz
tmplock=filelock_xyz_tmp$$ # me tohle staci :-)
touch $tmplock
# dulezita je volba -i (interactive) - aby se ptal, zda ma prespat a dostal odpoved "ne"
echo "n" | mv -i $tmplock $lockfile >&2
if [ ! -f $tmplock ]
then
echo "File lock made: $lockfile" >&2
break;
else
....
kazdopadne by me zajimal nazor nekoho kdo ma cas, chut videt do mv, resp. asi az jadra, zda je ta operace fakt atomicka... a tudiz funguje jako tsl, pokud ano tak si myslim, ze je to relativne rozumny zpusob jak to delat a hlavne nevyzaduje nejake speciality (zamykani na urovni fs, dalsi programy a jine "podivnosti" :-) )
nakonec jsem nekde vygoogloval reseniktere udajne pouziva firefox:
jadro problemu je v primititvu, ktera se obvykle teoreticky nazyva TSL (test-and-set lock) - cim ji implementovat na ruznych OS, shellech,atd...
reseni od firefoxaku je vyuzit operaci "mv", ktera z principu sve funkce ASI MELA BYT atomicka - bud se soubor presune nebo to ma skocnit s chybou ("jiz existuje-chcete prepsat?", nema prava, atd...)
takze postup:
lockfile=filelock_xyz
tmplock=filelock_xyz_tmp$$ # me tohle staci :-)
touch $tmplock
# dulezita je volba -i (interactive) - aby se ptal, zda ma prespat a dostal odpoved "ne"
echo "n" | mv -i $tmplock $lockfile >&2
if [ ! -f $tmplock ]
then
echo "File lock made: $lockfile" >&2
break;
else
....
kazdopadne by me zajimal nazor nekoho kdo ma cas, chut videt do mv, resp. asi az jadra, zda je ta operace fakt atomicka... a tudiz funguje jako tsl, pokud ano tak si myslim, ze je to relativne rozumny zpusob jak to delat a hlavne nevyzaduje nejake speciality (zamykani na urovni fs, dalsi programy a jine "podivnosti" :-) )
uživatel si přál zůstat v anonymitě
8. 4. 2008 16:27
Nový
Re: lockfile
celé vlákno
test existence souboru a nasledny presun jsou dve nezavisle operace. samotny presun potom bez reci prepisuje puvodni soubor. pro tyto ucely je mv k nicemu.
Stanislav Vokac (neregistrovaný)
---.commerzbank.com
4. 3. 2010 12:06
Nový
Re: lockfile
celé vláknoCo takhle „mv -i“ kterej se te zepta na konfirmaci prepsani. V noven shellu pak „pgrep mv | xargs kill –9“ a tim to na pozadi zabit a vyhodnotit navratovou hodnotu.
Mel by jsi tak navratovou hodnotu toho, jesli lockfile existuje i za pomoci prikazu mv.
Je to trochu prez ruku a dost zprasek, ale vidis, ze i pomoci mv to jde a tudiz neni jak rikas k nicemu.
13. 3. 2009 0:24
Nový
RE: Hrátky z řádky: pomocné soubory a zamykání
celé vlákno
Pokud jde jen o případ, aby se nestalo: "(kdy např. jeden program už čte to, co druhý ještě nedopsal)", tak bych možná využil raději práv než nějakých externích zámků.:
while [[ ! -a file || -w file ]]; do sleep 10; done
s tím, že ten zapisující po ukončení provede :
chmod 500 file
čímž uzavřel soubor pro zápis a je připraven pro čtení.
while [[ ! -a file || -w file ]]; do sleep 10; done
s tím, že ten zapisující po ukončení provede :
chmod 500 file
čímž uzavřel soubor pro zápis a je připraven pro čtení.

