GNU/Linux >> Znalost Linux >  >> Linux

Jaký je nejbezpečnější a nejpřenosnější způsob vyvolání binárního echa?

Všimněte si, že coreutils je softwarový balík vyvinutý projektem GNU, který poskytuje sadu základních unixových nástrojů pro systémy GNU. Najdete zde pouze coreutils echo na systémech GNU (Debian , trisquel , Cygwin , Fedora , CentOS ...). Na jiných systémech najdete jiný (obecně s jiným chováním jako echo je jednou z nejméně přenosných aplikací). FreeBSD bude mít FreeBSD echo , většina systémů založených na Linuxu bude mít busybox echo , AIX bude mít AIX echo ...

Některé systémy budou mít dokonce více než jeden (například /bin/echo a /usr/ucb/echo na Solarisu (poslední jmenovaný je součástí balíčku, který je nyní volitelný v pozdějších verzích Solarisu, jako je balíček for GNU utilities, ze kterého byste získali /usr/gnu/bin/echo ) všechny s různými CLI).

GNU coreutils byl portován na většinu unixových (a dokonce i neunixových, jako je MS Windows) systémů, takže byste byli schopni zkompilovat coreutils ' echo na většině systémů, ale to pravděpodobně není to, co hledáte.

Všimněte si také, že najdete nekompatibility mezi verzemi coreutils echo (například se dříve nerozpoznalo \x41 sekvence s -e ) a že jeho chování může být ovlivněno prostředím (POSIXLY_CORRECT proměnná).

Nyní ke spuštění echo ze systému souborů (nalezeno vyhledáním $PATH ), stejně jako u všech ostatních vestavěných funkcí je typický způsob env :

env echo this is not the builtin echo

V zsh (pokud neemulujete jiné shelly), můžete také:

command echo ...

aniž byste museli spouštět další env příkaz.

Ale doufám, že z výše uvedeného textu je jasné, že to nepomůže, pokud jde o přenositelnost. Pro přenositelnost a spolehlivost použijte printf místo toho.


# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
  or:  /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'

Myslím, že je to špatný nápad, abych byl upřímný, ale při hledání coreutils echo to udělá docela dobrou práci v rozumném prostředí. To jsou příkazy kompatibilní s POSIX (getconf , find , sh , grep , strings , printf , head ), takže by se měl chovat všude stejně. getconf nám poskytuje verze každého z těchto nástrojů kompatibilní s POSIX jako první v cestě v případech, kdy jsou výchozí verze nestandardní.

Najde jakýkoli spustitelný soubor, který obsahuje tisknutelné řetězce "GNU coreutils" a "Echo the STRING(s) to standardní výstup", které se objevují v GNU echo 's --help výstup a jsou doslova v textu programu. Pokud existuje více než jedna kopie, libovolně vybere tu první, kterou nalezne. Pokud není žádný nalezen, selže - $(...) expanduje na prázdný řetězec.

Nenazýval bych to však „bezpečným“, protože přítomnost tohoto (spustitelného) skriptu kdekoli v systému by vám způsobila určité potíže:

#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /

Takže abych to zopakoval, myslím, že je to velmi špatný nápad. Pokud se nechystáte přidat na seznam povolených hashů známých echo s, neexistuje žádný rozumný a přenosný způsob, jak najít danou verzi, která je bezpečná spustit na neznámých systémech. V určitém okamžiku budete muset spustit něco na základě odhadu.

Doporučuji vám použít printf místo toho, který přijímá formát a všechny argumenty, které chcete použít doslova.

# printf '%s' -e
-e

printf je v POSIX a měl by se chovat stejně pro všechny systémy, pokud zadáte formát.


Osobně se vyhýbám echo zcela v mých skriptech shellu a použijte printf '%s\n' blablabla když je řetězec krátký, a když je řetězec dlouhý, dokumentujte zde.

Citace z §11.14 Omezení Shell Builtins manuálu autoconf:

echo

Jednoduché echo je pravděpodobně nejpřekvapivějším zdrojem problémů s přenositelností. Není možné použít echo přenosné, pokud nejsou vynechány obě možnosti a sekvence escape. Nečekejte žádnou možnost.

V argumentech nepoužívejte zpětná lomítka, protože neexistuje jednotný názor na jejich zacházení. Pro echo '\n' | wc -l , sh společnosti Solaris výstupy 2 , ale Bash a Zsh (v sh režim emulace) výstup 1 . Problém je skutečně echo :všechny shelly rozumí '\n' jako řetězec složený ze zpětného lomítka a n . V rámci náhrady příkazu echo 'string\c' zkazí vnitřní stav ksh88 na AIX 6.1 takže vypíše první znak s pouze následovaný novým řádkem a poté zcela vypustit výstup dalšího echa v substituci příkazu.

Kvůli těmto problémům nepředávejte řetězec obsahující libovolné znaky do echo . Například echo "$foo" je bezpečné, pouze pokud víte, že foo Hodnota 's nemůže obsahovat zpětná lomítka a nemůže začínat - .

Pokud to nemusí být pravda, printf je obecně bezpečnější a jednodušší na použití než echo a echo -n . Proto skripty, kde přenositelnost není hlavním problémem, by měly používat printf '%s\n' kdykoli echo může selhat a podobně použijte printf %s místo echo -n . Pro přenosné skripty shellu se místo toho doporučuje použít dokument zde:

          cat <<EOF
          $foo
          EOF

Linux
  1. Nejpřenosnější způsob spuštění emulátoru terminálu?

  2. Přenosný (posix) způsob, jak dosáhnout substituce procesu?

  3. Cloudové zálohování vs. místní zálohování:Nejbezpečnější způsob ukládání dat

  1. Jaký je správný způsob použití inotify?

  2. Jaký je správný způsob vložení karty do sed?

  3. Jaký je správný způsob instalace jdk na linux

  1. Jaký byl nejdůležitější okamžik v historii Linuxu?

  2. Jaké je použití $# v Bash

  3. Jaký je nejbezpečnější způsob, jak umožnit uživateli přístup pro čtení k souboru protokolu?