it-swarm-eu.dev

Jak uniknout znaku jednoduché uvozovky v příkazu ssh/remote bash?

Stavím malou sadu skriptů pro vzdálené spouštění, zastavování a kontrolu stavu procesu. stop těchto skriptů by mělo hledat proces a zabít ho. Proto:

ssh [email protected] 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '{print $2}' | head -n 1`'

Problém je v tom, že krok awk tokenizace potřebuje jednoduché uvozovky a tyto střety jsou v rozporu s jednoduchou citací použitou pro provedení vzdáleného příkazu přes ssh. Jak lze tyto jednotlivé uvozovky uniknout?

19
SkyWalker

Použití

ssh [email protected] 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'{print $2}'"'"' | head -n 1`'
23
RedX

Nejedná se o ssh nebo awk manipulaci s uvozovkami, jedná se o prostředí Shell (a jsou nezbytné k tomu, aby Shell nemohl pracovat s jinými znaky, jako je například $). Vnoření je nepodporuje (i když jiné struktury, například $(), mohou vnořit i když obsahují uvozovky), takže budete muset uniknout jednotlivým uvozovkám zvlášť. Zde je několik metod:

$ echo 'Don'"'"'t mess with this apostrophe!'
Don't mess with this apostrophe!
$ echo 'Don'\''t mess with this apostrophe!'
Don't mess with this apostrophe!
12
Yann Vernier

Nelze zahrnout jednu citaci do řetězce s jednou uvozovkou. Nezáleží však na tom, protože jeden argument může mít více než jeden uvozený segment (pokud zde nejsou žádné nekótované mezery nebo jiné znaky s vlastním ohraničením).

Například:

ssh [email protected] 'kill -9 `ps -ef |
                 grep MapReduceNode |
                 grep -v "grep" |
                 awk -F " " '\''{print $2}'\'" |
                 head -n 1`"

Tento příkazový řádek je však very clunky. Pokud je to možné, měli byste použít pkill utility, což by snížilo vše na ssh [email protected] 'pkill -SIGKILL MapReduceNode'.

V opačném případě byste mohli provést veškerou manipulaci s řetězci v jediném vyvolání awk (netestováno, ale myslím, že to bude fungovat):

ssh [email protected] 'ps -ef |
                 awk "/[M]apReduceNode/{system(\"kill -9 \"$2)}"'

(Na rozdíl od originálu to zabije všechny úlohy MapReduceNode, spíše než nějaké první. Pokud opravdu chcete dělat jen jeden úkol, přidejte ; exit do akce awk.) 

8
rici

Existují další dvě možnosti, které nevidím v žádné z dalších odpovědí. Nechal jsem grep/grep/awk/head pipeline neporušený pro demonstrační účely, i když (jak je uvedeno v odpověď Rici ) to by mohlo být redukováno na něco jako

awk -F ' ' '/MapReduceNod[e]/ {print $2; exit}'
  1. Použití dvojitých uvozovek pro celý příkaz ssh:

    ssh [email protected] "kill -9 \$(ps -ef |
    grep MapReduceNode | grep -v \"grep\" | awk -F ' ' '{print \$2}' | head -n 1)"
    

    Všimněte si, že nyní mohu použít jednoduché uvozovky v příkazu, ale musím uniknout ostatním věcem, které nechci rozšířit: \$() (které jsem použil místo zpětných kopií), dvojité uvozovky \" a print \$2.

  2. Zde-doc s citovaným oddělovačem:

    ssh -T [email protected] <<'EOF'
    kill -9 $(ps -ef | grep MapReduceNode | grep -v 'grep' |
    awk -F ' ' '{print $2}' | head -n 1)
    EOF
    

    -T zabraňuje ssh stěžovat si na nepřidělení pseudo-terminálu.

    Zde-doc s citovaným oddělovačem je extra Nice, protože jeho obsah nemusí být upraven vůbec s ohledem na unikající věci, a může obsahovat jednoduché uvozovky.

5
Benjamin W.

Dalším příkladem je řešení jednoduchých nebo dvojitých uvozovek, protože pro mě například potřebuji interpretaci a variabilní nahrazení. Pokud chci vytvořit funkci pro zobrazení zprávy do makra mé ženy, mohu udělat následující:

ssh womanLptp "osascript -e 'tell app \"System Events\" to display dialog \"${1}\"'"
0
Pipo