Portál AbcLinuxu, 1. května 2025 19:00
Je to spíše takový vtip, nicméně jsem zjistil, že jsem opět udělal základní chybu (naštěstí si dávám pozor abych vše logoval a notifikoval.).
Ta hloupá chyba, je dána interpretací hodnot uvozených nulou. Pokud skript má dělat různé věci dle dne v měsíci, tak je asi nejsnadnější si zjistit den v měsíci a pak třeba IF-ovat.
Jenže pokud autor nemyslí a udělá:
today="$(/bin/date '+%d')" if [[ "${today}" -eq 1 ]]; then echo "Do action on the 1st of month..." fi
A hle ono to normálně funguje krom 8. a 9. dne měsíce. Zkuste si dnes 8.5. a ještě zítra… :)
No a je to prosté, protože 01-07 je v osmičkové soustavě OK (bo BASH nulou uvozené čísla bere jako oktalová) a od 10-31 je to už zas desítkově (bo tam není ta nula). Stačí jen trochu myslet a udělattoday="$(/bin/date '+%-d')"nebo může být případně i (mezera nevadí):
today="$(/bin/date '+%_d')" #kdo to nevidí je tam podtržítko.nebo explicitně převádět v dané soustavě:
today="$((10#$(/bin/date '+%d')))"nebo
if [[ "10#${today}" -eq 1 ]]; then …no a když už takto, tak asi nejlépe to dělat vše:
today="$(/bin/date '+%-d')" if [[ "10#${today}" -eq 8 || "10#${today}" -eq 9 ]]; then echo "Do action on the 8th or 9th of month..." fi
… a je pokoj a čisto…
(Ještě tam může být ošetření návratového kódu příkazu date
, ale nechtěl jsem to v ukázce natahovat…)
Takže jsem vám chtěl říct: „Kdybyste plánovali něco podobného, tak aby jste si na to dali pozor…“
Tiskni
Sdílej:
if [ "${today}" = "1" ]
a je to bez problémů. Kdysi do nás ve škole hustili, ať se skripty píšem čiště ve styly SysV. Ne, že bych to nějak striktně dodržoval (kolikrát ani nevím, co do toho ještě spadá a co už ne), ale koukám, že se to hodí, i když člověk nemusí předpokládat, že ten skrip poběží někde jinde než na Linuxu.
Možno lepšie by bolo to dať rovno do if.
Ovšem jen za předpokladu, že uděláš s date
to co jsem uvedl jako první, jinak tvoje if true
nenastane nikdy.
Bash má vlastní test a má rozdíly při použití [ ] vs. [[ ]] vs. (( )) - v tom je trochu rozdíl (, ale nic co by se toho týkalo).
A má operátory ==
(nebo kompatibilní =
) pro porovnání textové, co jsi použil a i -eq
(a další) pro porovnání numerické stejně jako test
, takže teď nevím ‚co‘ je ta finesa abych mohl říct ano či ne .
Mezi:
if [ "${today}" = "1" ]a
if [[ "${today}" == "1" ]]není zde rozdílu.
Jestli textově nebo numericky, to je těžké, na to je různý pohled, já většinou porovnám textově a paradoxem je právě, že jsem, zcela jistě, dal porovnání numerické aby 01 a 1 bylo totéž…
Jinak ksh taky [[
< > má BASH jako textové operátory (stejně jako dash, ksh), v csh už by to šlo numericky
S expr
je to nepřehledné (věc názoru), pokud se píše script pro bash či jiný shel, jedu to v něm s možnostmi, co má…
Podľa manu programu date je možne použiť aj výraz %e
a výsledok je podobný.
S jazykem kde, odsazování vytváří scope a furt chybí nějaký modul jsem trpělivost ani nikdy nezískal.
Ale jinak jestli bych měl scriptovat přes to co jsi odkázal, tak s tím seknu, to už nevidím pak důvod to nenapsat v nějakém normálním jazyku jako C/C++ a kdybych musel - nebo bych to dal raději v php.
S jazykem kde, odsazování vytváří scope a furt chybí nějaký modul jsem trpělivost ani nikdy nezískal.No, pointa nebyla v použití pythonu, ale v nepoužití bashe. Perl by taky šel. Jinak co se týče těch modulů, od toho je tady
pip
, přes který ten sh nainstaluješ stylem pip install sh
.
Ale jinak jestli bych měl scriptovat přes to co jsi odkázal, tak s tím seknu, to už nevidím pak důvod to nenapsat v nějakém normálním jazyku jako C/C++ a kdybych musel - nebo bych to dal raději v php.Zkoušel jsi někdy psát program, který pracuje se systémem v něčem, co jsi popsal? Většinou to má podporu tak asi jakože
system()
, s trochou štěstí se občas najde popen()
a kód pak vypadá stylem proveď system()
, zkontroluj návratový kód, přečti co to ti to vrátilo a doufej, že se to na pozadí nějak divně nerozpadlo. Je to asi tak intuitivní a přehledné jako se drbat za uchem živou chobotnicí.
Ten modul co jsem linkoval je poměrně vysokoúrovňový a na pozadí dělá různé triky, kterými se prakticky vyrovná stdin
/err
/out
je tam docela triviální. Používám to teď v práci na scriptování kolem proftpd a nemůžu si to vynachválit.
Zrovna to co jsi posílal by vypadalo takhle:
#! /usr/bin/env python import sh today = sh.date("+%d") if int(today) == 1: print "Do action on the 1st of month..."Když teda pominu, že pro práci s datumem a časem má python vlastní moduly, které jsou přítomné by default a na všech platformách.
Jsem si jistý, že ti to vyhovuje, ale jsem si jistý že mě ne a pokud nebudu muset budu jistě psát scripty v BASH nebo DASH či KSH atd…, v tom se vyzná každý…
Ale nedá mi to, bo na příkladu rozdíly moc nevidím, jen snad c-éčko je trochu delší:#! /usr/bin/env python import sh today = sh.date("+%d") if int(today) == 1: print "Do action on the 1st of month..."
#!/bin/bash today="$(/bin/date '+%-d')" if [[ "${today}" -eq 1 ]]; then # "10#${today}" echo "Do action on the 1st of month..." fi
<?php /*podle toho jak se to bude spouštět*/ $today = (int)date('j'); if ($today == 1){ echo "Do action on the 1st of month..."; }
#include <stdio.h> #include <time.h> int main(void) { time_t t = time(NULL); struct tm tm = *localtime(&t); if(tm.tm_mday == 1){ printf("%s", "Do action on the 1st of month..."); } }O možnostech a nemožnostech jednotlivých jazyků je to dost široký debata, bo způsob práce se liší a není třeba se prakticky vyrovnávat bashi/perlu, když máš BASH a PERL
O možnostech a nemožnostech jednotlivých jazyků je to dost široký debata, bo způsob práce se lišíEhm. To co jsi napsal v PHP a C není ekvivalent, neboť tam dochází k volání interních knihoven. Ta moje ukázka volá program
/bin/date
úplně stejně, jako ten bash kód. Pointa samozřejmě není takhle získávat datum, ale automatizovat ostatní procesy, keteré vyžadují interakci s programy, jenž nabízí shell. Způsob práce se tedy neliší od bashe.
a není třeba se prakticky vyrovnávat bashi/perlu, když máš BASH a PERLNo, to je na delší diskuzi. Pak se ti stává, že to dva dny v měsíci nefunguje ;) Já jsem docela rád, že python získal díky tomu modulu úplně jiný level použitelnosti pro věci, které bych dřív psal v bashi.![]()
Není to ekvivalent, protože provolání date
přes sytém nedokážu napsat, to mi paprče prostě nedají, ale bylo by samozřejmě to samé a v C by se to zkrátilo, protože by to bylo jen jedno volání.
To se ti stane v čemkoliv, když nerespektuješ definovaná pravidla (proto strašně nerad python, protože mám velké problémy je dodržovat a pak se divím a to mnohem častěji). Třeba v PHP, když si myslíš že AND a && je to samé nebo v csh, když si myslíš, že se s < porovná řetězce, nebo v C když si myslíš, že indexi pole jsou jako v Pascalu.
On ten způsob konverze řetězce v BASH není zas tak výjimečný, ono se to tak prostě někdy/někde dělá i ten python jenže explicitně, zápis int(today,0) způsobí stejný problém.
Není to ekvivalent, protože provolání date přes sytém nedokážu napsat, to mi paprče prostě nedají, ale bylo by samozřejmě to saméCo jsou to paprče?
a v C by se to zkrátilo, protože by to bylo jen jedno volání.No, to by ses mohl ještě divit, co všechno tam musíš řešit. Ono nestačí jen zavolat
system()
, protože ten pouze příkaz vykoná a vrátí status kód, nikoliv stdout
a stderr
.
To se ti stane v čemkoliv, když nerespektuješ definovaná pravidlaJenže ty pravidla jsou v bashi, jak to jen říct .. skrytější a nemilosrdnější. Prostě to není programovací jazyk a většina těch roztomilých vymožeností, které považujeme za normální tam chybí, nebo funguje lehce (a často skrytě) jinak.
(proto strašně nerad python, protože mám velké problémy je dodržovat a pak se divím a to mnohem častěji).Já ti nechci nutit python (což tak možná už vypadá :D), ale: V pythonu jsou ta pravidla maximálně triviální a konzistentní skrz celý jazyk. Celá syntaxe je tak triviální, že se vejde na pár desítek řádek BNF popisu a co je podstatné, tak je konzistentní. To bych si o bashi tvrdit netroufl, když v něm jednou za čas dělám třeba něco se smyčkama, tak mám pocit že ten kdo to navrhoval ujížděl na LSD a ještě to solil náhodným generátorem.
Rozšiř si slovní zásobu −> Paprče.
S C - ani bych se nedivil ;), jen jsem si to neuvědomil, kompletní varianta by byla opravdu o kus delší, nicméně jednou se napíše a pak se používá. I krátká varianta s popen bude delší.
Ono to o BASH bude asi trochu pravda, ale je to tím k čemu slouží s čím musí být kompatibilní.
S cykly nemám problém jsem to v zásadě omezil na while :; do
(výjimečně s podmínkou) a for((;;))
což jsou normální cykly (for .. in
h se někdy taky hodí, ale většinou zjistím, že vlastně potřebuji for((;;))
), ale někdy zápolím s podmínkami (chci používat jen [[ ]] a někdy mi to nevyjde)
Ostatně, zkoušel si někdo, jak je na tom PHP/perl/python oproti C/C++ ve skutečnosti? Jak už jsem tu někde psal, tak když jsem kdysi zkoušel napsat v PHP modul pro PowerDNS na načítání zone file z tinydns, tak jsem byl poměrně mile překvapen...Samozrejme zalezi jak kde ...
Pokud to pies pro sebe - proc ne, ale mit systemovy skripty v php na pracovnich systemech nebo vubec na strojich, s ktere administruje vic lidi. To radeji neNo to je docela otázka, proč by ne. Já to mám na pracovnich strojích, kde to adminuje víc lidí a vůbec to není problém. A to proto, že ty lidi, co ty skripty používaj, je používají podle toho, jak se používat mají a pokud není potřeba, tak se dovnitř nešahá. Což ostatně platí úplně u všech skriptů a programů. A pokud někdo už musí do zdrojáku, pak je výrazně podstatnější, jak přehledně je ten skript napsaný než v čem je napsaný.
To je taková všezahrnující odpověď. Ano, záleží jak kde, ale jak jsem psal, byl jsem mile překvapen, že ten rozdíl nebyl tak strašný, jak by se dalo očekávat. Pro představu: starý testovací stroj, nějaký P3 800MHz a zónový soubor s cca 40k DNS záznamy, což je už poměrně dost (řekněme třeba 1000 domén). Celé to zabralo 45MB RAMky a dotaz v průměru trval 0.00023 sekundy. Což je sice možná x-krát víc, než nativní aplikace v C, ale na druhou stranu je to naprosto dostačující. Ale přesto, když před někým řeknu "systémová věc napsaná v PHP", tak je to jak červený hadr na býka, odpovědi typu "To radeji ne", ale když se nad tím člověk objektivně zamyslí...Ostatně, zkoušel si někdo, jak je na tom PHP/perl/python oproti C/C++ ve skutečnosti? Jak už jsem tu někde psal, tak když jsem kdysi zkoušel napsat v PHP modul pro PowerDNS na načítání zone file z tinydns, tak jsem byl poměrně mile překvapen...Samozrejme zalezi jak kde ...
$ [[ "${today}" -eq 1 ]]; echo $? bash: [[: 09: value too great for base (error token is "09") 1I kdyz ten priklad by mel imho fungovat, i presto ze to "vybouchne".
lukas@x200:~$ date Fri May 9 20:50:21 BST 2014 lukas@x200:~$ today="$(/bin/date '+%d')" lukas@x200:~$ if [[ "${today}" -eq 1 ]]; then > echo "Do action on the 1st of month..." > fi bash: [[: 09: value too great for base (error token is "09")
Nerozumím řeči tvého kmene.
echo "$today" 09
-eq
porovnává čísla, tedy se $today převádí na číslo a protože string reprezentující číslo uvozený 0 se bere jako v osmičkové soustavě, tak to padne na hubu a hlásí ti to, že ani 8 ani 9 v osmičkové soustavě neexistuje, tak a to jsou ty dva dny v měsíci kdy to nefunguje a vo tom to celé je.
lukas@x200:~$ cat opravdu.sh if [[ 09 -eq 1 ]]; then echo "AAA" else echo "BBB" fi echo "afters" lukas@x200:~$ bash opravdu.sh opravdu.sh: line 1: [[: 09: value too great for base (error token is "09") BBB aftersbash no :-P
Dobře, nevyjádřil jsem se přesně nepadne to na hubu (ať to znamená cokoliv), o padnutí na hubu by se dalo mluvit pokud se má akce dělat 8 nebo 9 - ta by se neprovedla nikdy (nebo se právě 8 a 9 nemá dělat, což by se provedla).
A je to přece správně 09 se nerovná 1 (ani 9) protože to nelze porovnat, ale mnohem zajímavější (i když plně logické), pokud tam dáš -ne
bude to zas false a pokud to zneguješ ! bude furt true.
if [[ "08" -eq 8 ]]; then echo ok; else echo kwok;fi
bash: [[: 08: value too great for base (error token is "08")
kwok
if [[ "08" = "08" ]]; then echo ok; else echo kwok;fi
ok
prijde mi ta diskuse celkem dlouha a o nicem
Ano, použil si jednu z roje možností a porovnal jsi to textově (což sice lze, ale blbě se s tím počítá a jakmile začneš si tam kde jsem byl…), date vrací to, o co si řekneš a o tom to taky je a i většina z možností z diskuze je o tom jak funguje BASH a řekl bych, že diskuze je právě o těch možnostech, kde všechny jsou správně a každá je trochu jiná a jindy vhodná, pokud se ovšem neudělají chybně.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.