Strona 1 z 1
BASH - skrypt zwraca błąd przy inkrementacji "08"
: 02 maja 2020, 12:57
autor: chivito
Witam, wszystkich
Jestem nowym użytkownikiem na forum oraz w skryptach bashu.
Natrafiłem na taką sytuację jak w skrypcie poniżej.
Kod: Zaznacz cały
#!/bin/bash
while [ 1 ] ; do
#Tsec=$(date '+%S')
Tsec="08"
echo "sec in $Tsec"
#Tsec=$((Tsec+0))
Tsec=$((Tsec*1))
echo "sec out $Tsec"
sleep 1
done
I pytanie dlaczego sekunda ma wartość "08" skrypt sie wysypuje zwracając komunikat:
./format.sh: linia 14: 08: wartość za duża na podstawę (błędny znacznik to "08")
Programowaniem zajmuję się czysto hobbystycznie i nie do końca mam ogarniętą nomenklaturę.
W googlu nie udało mi się znaleźć odpwiedzi.
Re: skrypt bash zwraca błąd przy inkrementacji "08"
: 02 maja 2020, 14:46
autor: chivito
nie mam pojęcia o co chodzi ale trochę protestowałem i udało mi się uzyskać ciągłość pętli nieskończonej (już ponad godzinę) przez wstawienie dwóch if dla wartości 08 i 09 tak działa jak w kodzie poniżej:
Kod: Zaznacz cały
#!/bin/bash
while [ 1 ] ; do
Tsec=$(date '+%S')
if [ $Tsec = "08" ] ; then
Tsec=8
else
if [ $Tsec = "09" ] ; then
Tsec=9
fi
fi
echo "sec in $Tsec"
#Tsec=$((Tsec+0))
Tsec=$((Tsec*1))
echo "sec out $Tsec"
sleep 1
done
ktoś wie może skąd to się bierze?
Re: skrypt bash zwraca błąd przy inkrementacji "08"
: 02 maja 2020, 14:49
autor: dedito
Ten skrypt nie ma linii 14.
Błąd dotyczy linijki gdzie wykonujesz mnożenie Tsec=$((Tsec*1))
Jak chcesz mieć Tsec w formacie dwucyfrowym to rób to przy wyświetlaniu np. $(printf %02d $Tsec)
Re: skrypt bash zwraca błąd przy inkrementacji "08"
: 02 maja 2020, 16:33
autor: chivito
potrzebuję uzyskać bufor czasowy 1 sekundy do pobrania czasów z mysql, dla tego pobieram aktualną wartość sekund i ją inkrementuję.
w skrypcie głównym błąd generuje to miejsce:
echo użyłem tylko w skrypcie do testowania tego błędu. Błąd pojawia się taki sam i w tych samych sytuacjach.
Samo przypisanie Tsec=$(date '+%S') daje zawsze format dwucyfrowy.
Myślę że nie było by problemu gdy zwracana wartość była od 0...59 a nie od 00...59 tyle że w man dla date znałem instrukcje tylko dla godzini '+%k', która zwraca 0..23 a dla minut i sekund nie.
dzieje się tak samo dla każdej instrukcji #1 #2 #3
Kod: Zaznacz cały
#!/bin/bash
while [ 1 ] ; do
Tsec=$(date '+%S')
Tsec=$((Tsec+0)) #1
#Tsec=$((Tsec+1)) #2
#Tsec=$((Tsec*1)) #3
echo "sec out $Tsec"
sleep 1
done
działania wykonują się poprawnie gdy Tsec na wejściu zawiera 00...07 i 10...59
natomiast błąd pojawia się tak samo dla Tsec 08 i 09

Re: BASH - skrypt zwraca błąd przy inkrementacji "08"
: 02 maja 2020, 19:06
autor: dedito
chivito pisze: 02 maja 2020, 16:33
Myślę że nie było by problemu gdy zwracana wartość była od 0...59 a nie od 00...59 tyle że w man dla date znałem instrukcje tylko dla godzini '+%k', która zwraca 0..23 a dla minut i sekund nie.
Może nie jest to zbyt jasno opisane, ale w moim man date jest takie coś:
Domyślnie, date wypełnia pola numeryczne zerami. Następujące opcjonalne
modyfikatory mogą być umieszczone po %:
- (łącznik) nie wypełnia pola
Pobieraj sekundy bez zer wiodących.
Re: BASH - skrypt zwraca błąd przy inkrementacji "08"
: 03 maja 2020, 18:20
autor: lizard
W powłoce zapis
0n oznacza zapis w notacji ósemkowej, gdzie nie występują cyfry 8 ani 9.
Bash posiada zmienną
SECONDS, która zlicza sekundy od uruchomienia powłoki. Jest ona zapisywalna, więc można ja wyzerować:
Kod: Zaznacz cały
SECONDS=0
while true; do # ładniejsze od 'while [1]'
echo "sec out $SECONDS"
sleep 1
done
Jak chcesz zamienić ciąg znaków wyglądających jak liczba całkowita na liczbę użyj:
expr $Tsec + 0. Spacje są obowiązkowe.
Re: BASH - skrypt zwraca błąd przy inkrementacji "08"
: 04 maja 2020, 20:57
autor: chivito
Dobra powiem jak sprawa wygląda.
Ja to jestem architektem krajobrazu, który miał być elektronikiem a potem programistą.
Zamierzam postawić sterownik do nawadniania ogrodu na raspberry pi.
Interfejs napisałem w php+html z zapisem parametrów do mysql.
Skrypt w bash'u odpowiada za sterowanie czasowe, uruchamia się przez rc.local.
To jest mój pierwszy skrypt w bashu więc proszę o wyrozumiałą krytykę.
Na tą chwilę myślę że chyba powinienem go rozbić na kilka mniejszych skryptów, w tym jeden z pętlą główną.
Kod: Zaznacz cały
#!/bin/bash
#-----inicjalizacja portu GPIO
gpio write 1 1
gpio write 4 1
gpio write 5 1
gpio write 6 1
gpio write 10 1
gpio write 11 1
gpio write 31 1
gpio write 26 1
gpio write 27 1
gpio write 28 1
gpio mode 1 out
gpio mode 4 out
gpio mode 5 out
gpio mode 6 out
gpio mode 10 out
gpio mode 11 out
gpio mode 31 out
gpio mode 26 out
gpio mode 27 out
gpio mode 28 out
#-----odczekanie 30 sekund od startu systemu
x=0;
while [ $x -le 26 ] ; do
echo "$MESSAGE sec $x/30"
x=$((x+5));
sleep 5
done
#----pobranie aktualnego czasu
Thr=$(date '+%-H')
Thr=$((Thr+1))
if [ $Thr -eq 24 ] ; then
Thr=0;
fi
Tmin=$(date '+%-M')
Tsec=$(date '+%-S');
echo "godzina = $Thr"
echo "minuta = $Tmin"
echo "sec = $Tsec"
Tsec=$((Tsec+10))
if [ $Tsec -gt 59 ] ; then
Tsec=$((Tsec - 59))
fi
rr=0;
echo "sec = $Tsec"
#pobranie kolejnego startu jesli jest dostepny przed godzina 00:00:00
tab=$(echo "SELECT COUNT(*) FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr" | mysql -Dhomster -u user -ppasss -N)
StartNr="${tab[0]}";
echo "ilość startów przed nami: $StartNr"
if [ $StartNr -gt 0 ] ; then
tab=$(echo "SELECT hr FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartHr="${tab[0]}";
tab=$(echo "SELECT min FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartMin="${tab[0]}";
echo "kolejny start: $StartHr:$StartMin"
fi
#----ZEROWANIE POLECENIA SLEEP
Tsec=$(date '+%-S');
rr=$Tsec;
while [ $Tsec -eq $rr ] ; do
rr=$(date '+%-S');
done
#-----AKTUALIZACJA CZASU -----
Thr=$(date '+%-H')
Thr=$((Thr+1));
if [ $Thr -eq 24 ] ; then
Thr=0;
fi
Tmin=$(date '+%-M')
Tsec=$(date '+%-S')
StartJuz=0
rr=0;
#-----PETLA GLOWNA -----
while [ $rr -le 10 ] ; do # petla glowna
Tsec=$(date '+%-S')
echo "time $Thr:$Tmin:$Tsec"
if [ $Tsec -eq 0 ] ; then # zerowa sekunda
Tmin=$(date '+%-M')
if [ $Tmin -eq 0 ] ; then # zerowa minuta
Thr=$(date '+%-H')
Thr=$((Thr+1));
if [ $Thr -eq 24 ] ; then # zerowa godzina
Thr=0;
#pobranie pierwszego startu jesli jest dostepny przed godzina 00:00:00
tab=$(echo "SELECT COUNT(*) FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr" | mysql -Dhomster -u user -ppasss -N)
StartNr="${tab[0]}";
echo "ilość startów przed nami: $StartNr"
if [ $StartNr -gt 0 ] ; then
tab=$(echo "SELECT hr FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartHr="${tab[0]}";
tab=$(echo "SELECT min FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartMin="${tab[0]}";
echo "kolejny start: $StartHr:$StartMin"
fi # koniec pobierania czasu startu z bazy danych
fi # koniec ustawiania godziny 0
fi #koniec ustawiania godzin
if [ $StartNr -gt 0 ] ; then # jesli jest nastepny start
if [ $Thr -eq $StartHr ] ; then # oczekiwanie na godzine startu
if [ $Tmin -eq $StartMin ] ; then # oczekiwanie na minute startu
#-- START PROGRAMU -------------------------------------------------------------
echo "run program:"
mysql -u user -ppasss -Dhomster -e"UPDATE start_time SET stan=1 WHERE hr=$StartHr AND min=$StartMin;"
StartJuz=1
fi #koniec oczekiwania na minute startu
fi #koniec oczekiwania na godzine startu
fi #koniec oczekiwania na start
fi #koniec ustawiania minut
#-- OBSLUGA PROGRAMU ------------------------------------------------------------
if [ $StartJuz -eq 1 ] ; then
#pobieranie liczby sekcji do uruchomienia
tab=$(echo "SELECT COUNT(*) FROM item WHERE typid=2" | mysql -Dhomster -u user -ppasss -N)
num="${tab[0]}";
id=0;
#rozruch
gpio write 1 0 # wlaczenie pompy
mysql -u user -ppasss -Dhomster -e"UPDATE item SET stan=0 WHERE gpio=1;"
echo "ilosc sekcji: $num"
x=0;
while [ $x -lt $num ] ; do # petla pracy i przelaczania sekcji
x=$((x+1));
tab=$(echo "SELECT gpio FROM item WHERE id>$id AND typid=2 LIMIT 1" | mysql -Dhomster -u user -ppassss -N)
Vgpio="${tab[0]}";
tab=$(echo "SELECT stime FROM item WHERE id>$id AND typid=2 LIMIT 1" | mysql -Dhomster -u user ppasss -N)
Stime="${tab[0]}";
tab=$(echo "SELECT nazwa FROM item WHERE id>$id AND typid=2 LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
Sname="${tab[0]}";
tab=$(echo "SELECT id FROM item WHERE id>$id AND typid=2 LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
id="${tab[0]}";
echo "$x $Sname"
echo "gpio $Vgpio"
echo "time $Stime"
echo "----------"
gpio write $Vgpio 0
mysql -u user -ppasss -Dhomster -e"UPDATE item SET stan=0 WHERE gpio=$Vgpio;"
sleep $Stime
gpio write $Vgpio 1
mysql -u user -ppasss -Dhomster -e"UPDATE item SET stan=1 WHERE gpio=$Vgpio;"
done #koniec pracy przelaczania sekcji
gpio write 1 1 # wylaczenie pompy
mysql -u user -ppasss -Dhomster -e"UPDATE item SET stan=1 WHERE gpio=1;"
mysql -u user -ppasss -Dhomster -e"UPDATE start_time SET stan=0 WHERE hr=$StartHr AND min=$StartMin;"
#-- SPRAWDZENIE CZY JEST KOLEJNY START
#sprawdzenie bierzacego czasu
Thr=$(date '+%-H')
Thr=$((Thr+1));
if [ $Thr -eq 24 ] ; then
Thr=0;
fi
Tmin=$(date '+%-M')
Tsec=$(date '+%-S')
Tsec=$((Tsec+10))
if [ $Tsec -gt 59 ] ; then
Tsec=$((Tsec - 59))
fi
#pobranie pierwszego startu jesli jest dostepny przed godzina 00:00:00
tab=$(echo "SELECT COUNT(*) FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr" | mysql -Dhomster -u user -ppasss -N)
StartNr="${tab[0]}";
echo "ilość startów przed nami: $StartNr"
if [ $StartNr -gt 0 ] ; then
tab=$(echo "SELECT hr FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartHr="${tab[0]}";
tab=$(echo "SELECT min FROM start_time WHERE ( hr=$Thr AND min>=$Tmin ) OR hr>$Thr ORDER by hr, min LIMIT 1" | mysql -Dhomster -u user -ppasss -N)
StartMin="${tab[0]}";
echo "kolejny start: $StartHr:$StartMin"
fi # koniec pobierania czasu startu z bazy danych
#----ZEROWANIE POLECENIA SLEEP
Tsec=$(date '+%-S');
rr=$Tsec;
while [ $Tsec -eq $rr ] ; do
rr=$(date '+%-S');
rr=$((rr+0))
done
rr=0
Thr=$(date '+%-H')
Thr=$((Thr+1));
if [ $Thr -eq 24 ] ; then
Thr=0;
fi
Tmin=$(date '+%-M')
Tsec=$(date '+%-S')
StartJuz=0 # zerowanie wyzwolenia startu pracy
else
sleep 1
fi
done #koniec petli glownej
Re: BASH - skrypt zwraca błąd przy inkrementacji "08"
: 06 maja 2020, 11:36
autor: LordRuthwen
A nie próbowałeś użyć jakiegoś gotowca? Przecież takich projektów na RPi jest od groma.