Zašto ne sed -i / date -d / readlink -f u shell skriptama?¶
TL;DR
Pipeline runner-i su i macOS (BSD userland) i Linux (GNU userland). Isti shell flag na jednom radi, na drugom puca ili tiho korumpira fajl. Pravilo: FS / date / path u Pythonu, ne u shellu. Shell je samo za orkestraciju.
Tri zamke koje troše dane¶
sed -i — prazan string vs bez argumenta¶
# macOS (BSD) zahtijeva prazan string kao backup ekstenziju
sed -i '' 's/foo/bar/' file.txt
# Linux (GNU) NE SMIJE imati argument
sed -i 's/foo/bar/' file.txt
Ove dvije komande se jedna na drugu ruše bez greške. macOS GNU
flag tretira kao ime fajla, GNU macOS flag tretira kao komandu.
Rezultat: ništa se ne promijeni, ili se kreira file.txt-e backup,
ili se sve obriše.
Fix: Python (pathlib.Path.write_text ili
tempfile.NamedTemporaryFile + os.replace). Portable, atomic,
čitljiv.
date -d (GNU) vs date -v (BSD)¶
# GNU: "prije 3 dana"
date -d "3 days ago" +%Y-%m-%d
# BSD: ista stvar, drugi flag
date -v -3d +%Y-%m-%d
Isti cilj, potpuno druga sintaksa. CI skript koji prođe na macOS-u pukne na Linuxu (ili obrnuto).
Fix: Python datetime + timedelta. Isti kod svugdje.
readlink -f (GNU-only)¶
# GNU
readlink -f /path/to/file
# BSD: NE POSTOJI. Treba:
python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$path"
readlink bez -f na BSD-u ne prati lanac — readlink -f je
GNU ekstenzija koja nema BSD ekvivalent.
Fix: python3 -c 'import os, sys; print(os.path.realpath(...))'.
Zašto je bitno¶
ci-artifacts se vrti na:
- Self-hosted macOS (Mac mini) — BSD userland
- Self-hosted Linux (Hetzner) — GNU userland
Ista skripta mora raditi na oba. Shell trik optimizovan za jedan OS tiho korumpira produkciju na drugom. Najgori slučajevi su "tiho radi" — pipeline prođe, ali deploy je pogrešan.
Defanzivna pravila¶
- Sve FS mutacije kroz
pathlib.Path+os.replace(atomic). - Sve date math kroz
datetime+timedelta. - Sve path resolution kroz
os.path.realpath(ilipathlib). - OS provjera kroz
runner_detect.is_macos()/is_linux(), ne inlineplatform.system() == "Darwin".
Ili još bolje: ne treba ti OS check ako koristiš stdlib Python koji je cross-platform.
Kada shell JESTE u redu¶
- Orkestracija:
make,if,for,case - Testiranje exit kodova:
cmd && echo OK || echo FAIL - Globs i redirekcije
Ono što NE radimo u shellu:
- FS mutacije
- Date manipulacije
- Path resolution
- JSON parsing
- HTTP pozive (uvek u
vendor/api/api.py)
Vidi i¶
00-welcome.mdci/CLAUDE.md(root) — "Runtime environment" sekcija02-systems/11-vendor-api-contract.md— HTTP pozivi žive uapi/api.pyci/runner_detect.py—is_macos()/is_linux()