szkript "ráindítás" megakadályozása

Van egy mentő szkript, ami crontab-ból percenként indítva megvizsgálja, hogy egy bizonyos helyen egy fájl (flag-fájl) létezik-e?
Ha létezik, akkor törli a flag-fájlt és elindítja a mentést, különben meg kilép és nem csinál semmit.
A flagként használt fájlt egy Windowsos munkaállomás másolja a helyére egy mentes.bat programmal, amit Samba shareen ér el.
Ha a munkaállomás kezelője véletlenül elfelejti, hogy már elindította a mentést, akkor a flag-fájlt újból a helyére kerül és a crontab-ból futó szkript ismét elindítja a mentést.

Ezt a "ráindítást" hogy lehetne megakadályozni?

Persze van rá ötletem (a mentő fájl is elhelyez egy másik (tiltó) flag-fájlt és csak akkor törli le, ha a mentésekkel végzett), de talán van erre valamilyen szabályos vagy szokásos módszer is.
Lehet-e elegánsabban, --ami nem feltétlenül bonyolultabbat jelent--, is csinálni?

Hozzászólások

pisztolyt fogsz a rosszul klikkelő ember halántékához?

igen, a szabályos módszer pont az amit te is felvázoltál, úgy hívják ezeket hogy lock file:)

Szerintem jó az ötleted. A script az elején keres egy .backupisrunning, vagy hasonló fájlt pl a /tmp-ben, aztán ha nincs akkor kreál és kezdi a mentést, ha van akkor kilép. Ha tutira akarsz menni, akkor abba fájlba beleteheti a saját PID-jét és akkor még azt is le tudja ellenőrizni, hogy valóban fut-e, vagy csak beragadt a flaged, mert mondjuk az előző futás során elhasalt a cucc és nem lett törölve.

Köszi mindenkinek. Ezek szerint jó irányban gondolkodtam.
Ez a PID dolog elsőre nagyon megtetszett, én egy "echo $(date)>/tmp/mentes.lock"-ot csináltam eddig, csak hogy ne legyen üres a fájl.
Aztán tovább gondolva a PID-et úgy sem tudom visszaellenőrizni, mert nem a saját PID-del kell összehasonlítanom, csak azt kell megnéznem, hogy egy korábbi példány fut-e, aminek nem ismerem a PID-jét, de nem is kell ismernem.
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba és kész!

ha lock fájllal ellenőrzöd, hogy fut-e valami, akkor azt is ellenőrizni kell, hogyha ottvan a lock fájl, nem pusztult-e ki az a folyamat, ami egyszer letörli...

magyarul ha elindult a mentés, akkor a mentő script a saját pid-jét tegye bele a lock fájlba, te meg rendszeresen ellenőrizd, hogy van-e olyan pid-ű processz.

más megoldás, hogy felraksz egy bacula-t és nem szívsz a saját szkriptekkel.

Van egy mentő szkript, ami crontab-ból percenként indítva megvizsgálja, hogy egy bizonyos helyen egy fájl (flag-fájl) létezik-e?
Ha létezik, akkor törli a flag-fájlt és elindítja a mentést, különben meg kilép és nem csinál semmit.

IMHO: jó az amit írtál, mentés indításakor saját lock fájl, és mentés akkor és csak akkor, ha van flag és nincs létező lock fájl.

--
A gyors gondolat többet ér, mint a gyors mozdulat.

hát bashból talán a ps kimenetében megkereshetnéd a folyamat nevét, és ebből lehetne gondolkodni.
windows alatt ilyesmi a tasklist, viszont kellene valami grep alternativa is, ami nem tudom win parancssorban adott-e.
szerintem is a lock-file a legtutibb és talán a legegyszerűbb is.
----------------
...jönnek a gépek, a szemükben nincs harag...

lockfile helyett használd a flock programot.

a script elejére:

if [ x`ps aux | grep $0` != x ]; then exit; fi

ez garantálja, hogy csak egyszerre csak egy példányban fusson.

Az hagyján, de ha adódik még egy futó szkript, amelynek neve vagy vmelyik paramétere illeszkedik a $0-ra, lehet debuggolni a fekete mágiát.

pl. step1:
terminál:
vi /ezt/a/szkriptet/editalom.sh

cron:
futtatná az /ezt/a/szkriptet/editalom.sh-t, de a
ps aux | grep /ezt/a/szkriptet/editalom.sh
találata nem hagyja

step2:
mi a #!@#$%^$^! (vi off) futtatás kézből - lefut - ahhha, akkor a cron a hibás! de nem látszik ott baki, ráadául most a cron is lefuttatja... hmm... akkor vi... goto step1 az érme alázuhanásáig

Persze lehet tovább gányolni, hogy ez ne így legyen - kutyaharapást szőrivel. :)

Az benne a gányolás, hogy megint csak nem fed le mindent.

Ismét példa: korrektúrázva a grep, hogy csak azt találja meg, amit meg kell találnia. Örülünk?
Sajnos csak addig, amíg valaki (pl. uaz, aki a szkriptet írta, csak picit álmos) el nem indítja kézből a programot, valamilyen adott esetben logikus, de előre nem látott relatív úttal, legvalószínűbben ./szkript.sh formában.

Persze, ezt is le lehet védeni...

Sot, valahogy ugy is indithatja, hogy sh -x valamiscript.sh. Persze, fel lehet keszulni idiotasagokra, de konyorgom, ha jol tudom, ez egy mento rendszer lesz, ezt imho ember kezzel nem fogja felloni, ha megis, akkor gondolom kezletores betekint. Sajnos nem lehet mindent levedeni shell scriptbol.
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

"pgerp-re cserélem a grep-et"

bocs, nem azért írtam, hogy cseréld le, hanem úgy értettem, hogy a
ps -ef foobar.sh | grep -v grep

helyett gyakran elegánsabb egy pgrep foobar.sh

Csak éppen nem ebben a problémában, mert
egyáltalán nem jó az a megközelítés, hogy a futó processzek között turkálva akarod megakadályozni a többszörös futtatást.


PID=$$
LF="/tmp/vmi.pid"
if [ -f $LF ]; then
        if $(cmp -s /proc/$(cat $LF)/cmdline /proc/$PID/cmdline); then
                echo "mar fut"
                exit 1
        fi
fi
echo $PID > $LF

vagy


PID=$$
LF="/tmp/vmi.pid"

if [ -f $LF ]; then
        pc=$(cat $LF)
        pcpid=${pc%:*}
        pccmd=${pc#*:}
        if [ -d /proc/$pcpid ]; then
                cmdline=$(cat /proc/$pcpid/cmdline)
                if [ "$cmdline" == "$pccmd" ]; then
                        echo "Mar fut"
                        exit 1
                fi
        fi
fi

echo "$PID:$(cat /proc/$PID/cmdline)" > $LF

/var/lock/scripted.lock fájl ha létezik a script indulásakor akkor kilép, ha nem, akkor belerakja a pid-jét, és a script végén, ha a benne lévő pid a sajátja(!), akkor törli.

Ezt én egy plusz trükkel megspékelném: nem cron-ból futtatnám, hanem inittabból, respawn-nal úgy, hogy a script futási idejét egy sleep 60 -nal egy percre, vagy picit fölé tornáznám.

ne cron-ból fusson, hanem incron-ból, így nincs polling. incron-ban megadható, hogy akkor aktivizálja a script-et pl, ha az írás befejeződött a figyelt mappában. az incron azért jó, mert kernel eseményre aktivizálódik (man incrond).


incrontab -e

/figyelt/mappa IN_CLOSE_WRITE script.sh "$@/$#"

amúgy meg:

man lockfile-progs

mindenképpen lockfile-al csináljad és ne ps meg grep trükközésekkel, mert egy csomó rejtett buktató van (pl. mi van ha akkor indul a másik script, amikor már fut az első, de még nem jött létre a lockfile stb.)

én a manual alapján így használom:


# lock file mechanism to make sure only one instance of the script is running
LOCK="/tmp/`basename $0`.lock"
lockfile-create "$LOCK" || exit 1
lockfile-touch "$LOCK" &
PID="$!"
rm /figyelt/mappa/file


echo whatever..


kill "$PID"
lockfile-remove "$LOCK"

másik megoldásnak azt ajánlanám, hogy mi lenne ha a script-ed figyelne nc-vel egy portot, és a win-es gépről telnet-tel tolnál át parancs byte-okat a mentésre. a tűzfalon persze csak az adott gép mac címét vagy ip-jét engedélyeznéd ehhez a porthoz. pl:


while true; do

if nc -l -p 9999 | grep mycommand; then

  echo do it now

fi

done

vagy


while true; do

COMM=`nc -l -p 9999`

if echo $COMM | grep command1; then echo do 1st; fi
if echo $COMM | grep command2; then echo do 2nd; fi
if echo $COMM | grep command3; then echo do 3rd; fi

done

---------------------
windows oldalról meg tölts le win-es netcat portot, aztán batch fájlba vagy terminálba windows-on:


echo command1 | nc.exe -w 1 szerverip 9999