Apple představil (YouTube) telefony iPhone 17 Pro a iPhone 17 Pro Max, iPhone 17 a iPhone Air, sluchátka AirPods Pro 3 a hodinky Watch Series 11, Watch SE 3 a Watch Ultra 3.
Realtimová strategie Warzone 2100 (Wikipedie) byla vydána ve verzi 4.6.0. Podrobný přehled novinek, změn a oprav v ChangeLogu na GitHubu. Nejnovější verzi Warzone 2100 lze již instalovat také ze Snapcraftu a Flathubu.
Polské vývojářské studio CD Projekt Red publikovalo na Printables.com 3D modely z počítačové hry Cyberpunk 2077.
Organizátoři konference LinuxDays 2025 vydali program a zároveň otevřeli registrace. Akce se uskuteční 4. a 5. října na FIT ČVUT v pražských Dejvicích, kde vás čekají přednášky, workshopy, stánky a spousta šikovných lidí. Vstup na akci je zdarma.
Uživatelé komunikátoru Signal si mohou svá data přímo v Signalu bezpečně zálohovat a v případě rozbití nebo ztráty telefonu následně na novém telefonu obnovit. Zálohování posledních 45 dnů je zdarma. Nad 45 dnů je zpoplatněno částkou 1,99 dolaru měsíčně.
Server Groklaw, zaměřený na kauzy jako právní spory SCO týkající se Linuxu, skončil před 12 lety, resp. doména stále existuje, ale web obsahuje spam propagující hazardní hry. LWN.net proto v úvodníku připomíná důležitost zachovávání komunitních zdrojů a upozorňuje, že Internet Archive je také jen jeden.
Jakub Vrána vydal Adminer ve verzi 5.4.0: "Delší dobu se v Admineru neobjevila žádná závažná chyba, tak jsem nemusel vydávat novou verzi, až počet změn hodně nabobtnal."
V Německu slavnostně uvedli do provozu (en) nejrychlejší počítač v Evropě. Superpočítač Jupiter se nachází ve výzkumném ústavu v Jülichu na západě země, podle německého kancléře Friedricha Merze otevírá nové možnosti pro trénování modelů umělé inteligence (AI) i pro vědecké simulace. Superpočítač Jupiter je nejrychlejší v Evropě a čtvrtý nejrychlejší na světě (TOP500). „Chceme, aby se z Německa stal národ umělé inteligence,“ uvedl na
… více »V Berlíně probíhá konference vývojářů a uživatelů desktopového prostředí KDE Plasma Akademy 2025. Při té příležitosti byla oznámena alfa verze nové linuxové distribuce KDE Linux.
Byl vydán Debian 13.1, tj. první opravná verze Debianu 13 s kódovým názvem Trixie a Debian 12.12, tj. dvanáctá opravná verze Debianu 12 s kódovým názvem Bookworm. Řešeny jsou především bezpečnostní problémy, ale také několik vážných chyb. Instalační média Debianu 13 a Debianu 12 lze samozřejmě nadále k instalaci používat. Po instalaci stačí systém aktualizovat.
Má-li skript fungující v Bashi hashbang "#!/bin/sh", mělo by to znamenat, že jej lze spustit i pomocí Bourne shellu, dash a ksh. Pokud tomu tak není, je vhodné jej změnit na "#!/bin/bash" nebo jej přepsat. Jak se rozhodnout?
Jak už zde zaznělo, silným argumentem pro používání standardní syntaxe Bourne shellu (a kompatibilních shellů, jako je dash či ksh) je zpětná kompatibilita, která ovšem souvisí i s externími nástroji, které ze skriptu voláte. Dalším kladem je (v některých případech) rychlost vykonávání, která je zpravidla u jednodušších shellů vyšší. Jiný argument pro je ten, že menší shell je vhodnější pro nasazení na mobilní či embedded zařízení s omezenými zdroji (málo paměti, pomalý procesor).
Pokud pro vás ovšem zmíněné vlastnosti nejsou důležité, pak asi neexistuje pádný důvod se nějak omezovat. Například skript pro převod videa zaprvé nebude mít pravděpodobně tak dlouhou životnost, aby bylo nutné si nějak zvlášť lámat hlavu s kompatibilitou a co se týče embedded zařízení, tak pro ty takový skript z principu není určený. Pokud vás zaujala zpětná kompatibilita, je třeba si uvědomit, že ta souvisí i s používáním kompatibilních externích nástrojů – budete-li například v shellovém skriptu používat rozšíření nástrojů GNU (oproti standardu), tak to poněkud postrádá smysl. V každém případě je třeba nejprve se rozhodnout, zda přepis nebude jen ztrátou času.
Lidé v Bashi často nahrazují příkaz test
voláním [[
, které je (dle mého zkoumání) z nějakého důvodu rychlejší než [
. Toto je ovšem nekompatibilní. Zrovna tak není možné používat "(( ))" nebo "$[ ]". Ovšem "$(( ))" funguje, i když oproti Bashi omezeně. Ukázka v Bashi:
#!/bin/bash x=0 ((x++)) x=$[x+1] if((x==2)); then echo "V pořádku..." fi file="/tmp/testfile" [[ ! -e "$file" ]] && echo "$file neexistuje"
Kdyby tento skript dával smysl a vyplatilo se nám ho přepisovat, přepis by vypadal takto:
#!/bin/sh x=0 : $(( x+=2 )) if [ "$x" -eq 2 ]; then echo "V pořádku..." fi file="/tmp/testfile" [ ! -e "$file" ] && echo "$file neexistuje"
Test "[" je v klasickém shellu omezený oproti Bashi, například pro porovnání dvou řetězců nepoužívá operátor "==", ale "=". Někdy se v Bashi můžete setkat s přesměrováním "<<<", které přesměruje zadaný řetězec na standardní vstup programu. Na takové vychytávky zapomeňte, místo toho je třeba použít například echo
či printf
a příkaz dát za rouru:
# bash [ "$1" == "$2" ] && tr -d 'x' <<< "xxaxxhxxoxxjx" # sh [ "$1" = "$2" ] && echo "xxaxxhxxoxxjx" | tr -d 'x'
Podstatná věc, na kterou v sh
můžete zapomenout, jsou pole. Je to jedna z věcí, která může zkomplikovat přepis skriptu. Bash má také více vestavěných funkcí a klíčových slov: v sh
neexistuje declare
, disown
, shopt
, time
, select
a function
či let
. Některé vestavěné funkce, které má sh
společné s Bashem, jsou ochuzené o různé přepínače či funcionalitu, například echo
nemá přepínač -e a read
vyžaduje název proměnné.
Zrovna tak není možné přesměrovat standardní vstup i výstup najednou pomocí &> soubor
, ale je třeba použít > soubor 2>&1
.
### Bash function f { echo -e "\n\nTest" >&2 read echo ${REPLY:-nic...} } f &> out ### sh f() { printf "\n\nTest\n" >&2 read REPLY echo ${REPLY:-nic...} } f > out 2>&1
Pochopitelně nefungují ani věci jako PATH+=":~/bin"
nebo ${!BASH*}
. Místo {1..10}
je potřeba použít $(seq 1 10)
a $UID
je nutné nahradit za $(id -ru)
. V sh
také není source
, místo toho lze použít jednoduše .
(tečku).
### Bash source /etc/profile PATH+="~/bin" uid="$UID" ### sh . /etc/profile PATH="$PATH:$HOME/bin" # sh neprovádí expanzi "~" v PATH uid="$(id -ru)"
Tolik tedy k základním věcem, na které je třeba dát si pozor. Na anglické Ubuntu wiki se tímto tématem zabývají také, viz Dash as /bin/sh. Pochopitelně, pokud chcete mít jistotu, že je skript kompatibilní se sh
, tak není nic jednoduššího, než jej spustit např. pomocí dash
.
checkbashisms
Vývojáři Debianu v polovině roku 2010 odstraňovali použití Bashe ze sestavovacích skriptů a při té příležitosti napsali v Perlu program checkbashisms
, který se snaží detekovat některé "bashismy", což je označení pro nekompatibilní rozšíření Bashe. V některých případech rovnou vypisuje i náznak triviálního řešení.
possible bashism in /tmp/ncoda line 235 (alternative test command ([[ foo ]] should be [ foo ])): if [[ "$oformat" == "wav" ]]; then possible bashism in /tmp/ncoda line 235 (should be 'b = a'): if [[ "$oformat" == "wav" ]]; then possible bashism in /tmp/ncoda line 253 (<<< here string): oformat="$(tr '[[:upper:]]' '[[:lower:]]' <<< "$oformat")" possible bashism in /tmp/ncoda line 368 (declare): declare option_${OPTION}=true possible bashism in /tmp/ncoda line 385 ('((' should be '$(('): if (( $# == 0 )); then
V tomto výpisu je pět řádků, které by bylo třeba upravit, aby bylo korektní použít hashbang #!/bin/sh
. Každý z těchto konkrétních případů jsem popsal v článku.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
((x++));
do POSIXu, je toto:
: $(( x+=1 ));
což má výhodu, že jméno proměnné píšete jen jednou.
Řetězec na vstup dostanete taky here-docem (výhoda: dá se použít i pro jiné deskriptory než 0):
command <<E1 3<<E2
... tohle jde na fd 0
E1
... a tohle na 3
E2
Ale pokud mam slozitejsi skript, tak zrovna [[ expr ]] urcite nechci nahrazovat, protoze [[ expr ]] je build-in a [ expr ] mi forkne dalsi proces. Proto je taky [[ rychlejsi..
V bashi jsou i test
a [
builtin. Smysl [[ ... ]]
vidím jen v tom, že má navíc operátor =~
(matchování regulárních výrazů) a že =
, ==
a !=
matchují podle wildcards. Což ale může být dost matoucí, protože jsem přesvědčen, že nemalá část těch, kdo [[ ... ]]
používají, tohle neví a myslí si, že porovnávají na rovnost.
[ expr ] mi forkne dalsi procesOpravdu? Najděte mi tedy ten fork:
jirka@debian:/tmp$ strace sh -c '[ 0 = 0 ]' execve("/bin/sh", ["sh", "-c", "[ 0 = 0 ]"], [/* 46 vars */]) = 0 brk(0) = 0x805f000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb785d000 access("/etc/ld.so.preload", R_OK) = 0 open("/etc/ld.so.preload", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=35, ...}) = 0 mmap2(NULL, 35, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = 0xb785c000 close(3) = 0 munmap(0xb785c000, 35) = 0 open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=140547, ...}) = 0 mmap2(NULL, 140547, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb783a000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i686/cmov/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320m\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1323460, ...}) = 0 mmap2(NULL, 1333608, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76f4000 mmap2(0xb7834000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x13f) = 0xb7834000 mmap2(0xb7837000, 10600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7837000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f3000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb76f38d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb7834000, 8192, PROT_READ) = 0 mprotect(0xb787b000, 4096, PROT_READ) = 0 munmap(0xb783a000, 140547) = 0 getpid() = 20048 rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 geteuid32() = 1000 brk(0) = 0x805f000 brk(0x8080000) = 0x8080000 getppid() = 20047 stat64("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=16384, ...}) = 0 stat64(".", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=16384, ...}) = 0 rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGINT, {0x8056520, ~[RTMIN RT_1], 0}, NULL, 8) = 0 rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGQUIT, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0 rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTERM, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0 exit_group(0) = ?Tohle je dash, ale v bashi je to podobný, jen delší.
a pritom bys mel psat #!/usr/bin/env bashJako aby mi ty skripty nefungovaly při startu systému, pokud mám /usr na samostatném oddílu, jo?
Zrovna tak není možné přesměrovat standardní vstup i výstup...nema tam byt standartni i chybovy vystup?
Nebijte mě, ale boot trvá tak 20 - 30 s včetně bios.Jasně, takhle dlouho trvá i na Arch Linuxu, kterej má initskripty v Bashi. Takže zkrácení o desítky sekund by bylo v podstatě zrušení bootu
x=$((x+1))
urcite neni kompatibilni s Bourne Shell.
$ sh -c 'x=1; x=$((x+1))'
sh: syntax error at line 1: `x=$' unexpected
$ sh -c 'x=1; x=$(($x+1))'
sh: syntax error at line 1: `x=$' unexpected
To je feature az od Korn Shell.
read
dostane do podprocesu, těžko si šáhneme na proměnné z jeho výstupu:
read auto <<< $(echo nazdar | tr nr 'M '); echo $auto # Funguje, protože proměnná $auto je ve stejném shellu
echo nazdar | tr nr 'M ' | read auto; echo $auto # Většinou nefunguje, protože proměnná $auto zmizí i se svým podprocesem, viz níže
A někdy vás to opravdu překvapí - jako když ten příkaz read z příkladu výše začne najednou někde fungovat - a objevíte tím pádem nenápadnou větu z manuálové stránky ksh, sekce pipeline:
Each command, except possibly the last, is run as a separate process;A to jsou jen dvě drobnosti namátkou. Navíc autor článku správně zmiňuje fakt, že nemá smysl přepisovat konstrukce ve skriptu, když by člověk zůstal u GNU rozšíření ostatních programů - takže se k tomu přidají další konstrukce obcházející tyto nedostatky - a kód roste a roste... Zkrátka, je to procházka růžovým sadem (z pohledu ostatních - přeci si jen hraješ se skripty, co na tom je? Žádné programování kernelu...), kde v každém růžovém keři je minimálně jeden Semtex (z pohledu těch, co to zkusili). Kdysi jsem měl dvě nabídky práce: buď dělat v céčku a s Oracle databází nebo za o polovinu vyšší plat jít do jedné banky spravovat jejich shellové skripty. Zvolil jsem to první - a když jsem pak pomáhal s pár skripty pro zákazníky, pochopil jsem, jak moc mě v té chvíli osvítilo, že jsem se nenechal penězi zlákat...
function a { typeset var localvariable = 0; }V tomto pripade promenna localvariable neni lokalni a je inicializovana pouze jednou. Pokud by ale byla fce "a" deklarovana jako "function a()" tak by byla localvariable inicializovana pri kazdem volani.
Lidé v Bashi často používají příkaztest
voláním[[
, …
Tady asi mělo být spíš nahrazují než používají.
sh
") je definováno POSIXem (příslušná kapitola v poslední verzi zde, rozhodně lze doporučit k přečtení). Příliš nechápu, proč je v článku sh
volně zaměňován s dash
em. Skoro mi až přijde, že v tom sám autor má tak trochu zmatek, slovo POSIX se v článku neobjevuje ani jednou...
echo $(whoami)
echo `whoami`btw, jak se da napsat ` ve windows?
Na druhou stranu tam znak ` nikde nepotřebujete, leda byste byl úchyl používající šmejďárnu typu cygwin.A co pracovat vzdáleně na nějakém unixu?
sh
je tento:
$ echo $(whoami) syntax error: `(' unexpected $ echo `whoami` daveV bashi je ovšem často pohodlnější používat
$( )
. Je to přehlednější (zvlášť při vnořování), nedá se to snadno zaměnit.
A nakonec rozdíl (v bashi):
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $( command ) form, all characters between the parentheses make up the command; none are treated specially.
$ uname -a SunOS srv 5.6 Generic_105181-39 sun4u sparc SUNW,Ultra-5_10 $ echo $(whoami) ksh: whoami: not found $ echo $(who am i) xxxxxxx pts/1 Feb 17 12:20 (xxxxxxxxxxx) $ sh $ echo $(whoami) syntax error: `(' unexpected
# uname -a SunOS dedek 5.6 Generic_105181-39 sun4u sparc SUNW,Ultra-5_10 # exec /usr/xpg4/bin/sh # echo $(/usr/ucb/whoami) juzrVyřešeno, byť systém už dávno není podporován, léta na něj neexistují patche a jen blázen by nechával v produkci cokoli staršího než Solaris 9. A po celou dobu až do současných verzí je to pořád stejné, na stejném místě a se stejným chováním. A překvapení, i AIX má /usr/ucb a hle, AIXovský /bin/sh je ve skutečnosti normovaný ksh a většina toolů v AIXu je prostě POSIX/XPG4. Pokud chcete přenositelnost, nezbývá než číst dokumentaci (
Zase někdo, kdo tvrdí, že něco nejdenetvrdim, ze neco nejde. jen jsem reagoval na skutecnost, ze vychozi nastaveni muze nekoho prekvapit, pokud se systemem bezne nepracuje. takze jste se zbytecne rozepisoval, ale treba to nekomu jinemu poskytlo zajimave informace.
[ conditional_expr ] # Provided for Bourne shell compatibility (obsolete) [[ conditional_expr ]] # POSIX and Korn shell specific syntax (preferred)... Tak nevím...
nebo dokonce jejich kombinacíPomocí kombinace se na české píše jenom pípa
|
, ale na spoustě klávesnic je „pička key“ (klávesa označovaná v GNOME jako <|>
), která píše | a \.
Mně zase přijde praktičtější zvyknout si na jedno rozložení a pak používat to. Ale je pravda, že takových jako já asi moc není.Já taky používám pořád českou QWERTY. Ze známých osobností pak minimálně RH a to už něco znamenánebo dokonce jejich kombinací
...se přestal používat ve skriptech na úkor o dost výkonnějšího Dash...Ach jo.
?? Ach ne....se přestal používat ve skriptech na úkor o dost výkonnějšího Dash...Ach jo.