Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: hazardrok 01. 03. 2023, 14:11:24
-
Ahoj, laboruju se skriptem v bashi ve kterém se snažím třídit databázový soubor. Třídění mi funguje, ale překvapilo mě chování proměné "OPAKOVAT"
#!/bin/bash
exit_status=0
while true; do
OPAKOVAT=0
find /opt/databaze_pracovni -name "database.db" -exec sh -c '
for file do
dir=${file%/*}
echo "$dir"
/home/irma/database_sort_new "$dir"
OPAKOVAT=1
done' sh {} +
echo $OPAKOVAT
if [ $OPAKOVAT -eq 1 ]; then
echo "nebude se uspavat"
continue
fi
echo "sleep"
sleep 300s
done
Zjistil jsem, že proměná "OPAKOVAT" se mi na konci skriptu nikdy nevyhodnotí jako "1" a to i přes to, že vždy najdu několik databázových souborů takže cyklus vždy proběhne. Můžete mi prosím někdo poradit co dělám špatně? Dík
-
protoze to OPAKOVAT=1 volate v novem shellu (exec sh -c) a to je pouze lokalni pro dany shell a vysledek se vam nedostane mimo ten for cyklus.
-
Super...dík za radu. To ale rozhodně nebyl můj záměr. Když jsem ten script tvořil tak jsem prostě googlil a zkoušel různý věci aby to dělalo to co potřebuji a je to několik let zpátky. Nyní potřebuji s tím zas něco jiného a nestačím se divit :-)
Tak se zeptám ještě na jednu věc....jak z toho ven, resp. lze to nějak jednoduše upravit nebo je potřeba znovu zapátrat?
Dík.
-
pokud mi neco neunika, tak ten find odstavec resit normalne=obracene :-)
while read file; do
dir=${file%/*}
echo "${dir}"
/home/irma/database_sort_new "${dir}"
OPAKOVAT=1
done < <(find /opt/databaze_pracovni -name "database.db")
-
pusť to s pomocí sh -x na debug
taky export OPAKOVAT by neškodil
-
protoze to OPAKOVAT=1 volate v novem shellu (exec sh -c) a to je pouze lokalni pro dany shell a vysledek se vam nedostane mimo ten for cyklus.
ano, jsou to defacto dvě různé proměnné.
-
pusť to s pomocí sh -x na debug
taky export OPAKOVAT by neškodil
https://www.baeldung.com/linux/bash-variables-export
-
zkusil jsem zase chatgpt :-) ne že bych to měl zapotřebí :-) ani jsem to netestoval
a koukám, že už to psal k3dar
Problém je v tom, že hodnota proměnné OPAKOVAT se nastaví uvnitř podshellu, který je spuštěn pomocí příkazu sh -c. Proměnná OPAKOVAT v této podobě existuje pouze v kontextu podshellu a změna hodnoty se neodráží na proměnné OPAKOVAT v nadřazeném shellu.
Jednou z možností, jak toto řešit, je použít přímý způsob komunikace mezi podshellem a nadřazeným shellem pomocí standardního výstupu a standardního vstupu. Můžete to provést následovně:
#!/bin/bash
declare -i OPAKOVAT=0
exit_status=0
while true; do
OPAKOVAT=0
while read -r dir; do
echo "$dir"
/home/irma/database_sort_new "$dir"
OPAKOVAT=1
done < <(find /opt/databaze_pracovni -name "database.db" -exec dirname {} \;)
echo $OPAKOVAT
if [ $OPAKOVAT -eq 1 ]; then
echo "nebude se uspavat"
continue
fi
echo "sleep"
sleep 300
done
Tento skript používá konstrukci < <() pro spuštění podshellu, který získává seznam adresářů obsahujících soubor database.db. Tento seznam je předán do cyklu while pomocí standardního vstupu, kde se každý adresář zpracovává a nastavuje se proměnná OPAKOVAT.
-
pokud mi neco neunika, tak ten find odstavec resit normalne=obracene :-)
while read file; do
dir=${file%/*}
echo "${dir}"
/home/irma/database_sort_new "${dir}"
OPAKOVAT=1
done < <(find /opt/databaze_pracovni -name "database.db")
Asi ti nic neuniklo....toto funguje. Dík za pomoc, protože tohle mi ušetří spoustu nervů :-)