Як я можу виконувати локальний скрипт на віддаленій машині та включати аргументи?


116

Я написав сценарій, який добре працює, коли виконується локально:

./sysMole -time Aug 18 18

Аргументи "-time" , "Aug" , "18" та "18" успішно передаються до сценарію.

Тепер цей сценарій розроблений для виконання на віддаленій машині, але з локального каталогу на локальній машині. Приклад:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

Це також чудово працює. Але проблема виникає, коли я намагаюся включити ці вищезгадані аргументи (наприклад, час 18 серпня 18) , наприклад:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

Після запуску цього сценарію я отримую таку помилку:

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

Скажіть, будь ласка, що я роблю неправильно, це сильно засмучує.


1
"Bash -s" - це один із способів виконання сценарію зі стандартного вводу (тобто файлу).
AllenD

Відповіді:


160

Ви були досить близькими зі своїм прикладом. Він працює чудово, коли ви використовуєте його з такими аргументами.

Приклад сценарію:

$ more ex.bash 
#!/bin/bash

echo $1 $2

Приклад, який працює:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

Але це не вдається для таких типів аргументів:

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

Що відбувається?

Проблема, з якою ви стикаєтесь, полягає в тому, що аргумент, -timeабо --timeв моєму прикладі, трактується як перехід на bash -s. Ви можете умиротворити bash, припинивши його взяти будь-який з решти аргументів командного рядка для себе, використовуючи --аргумент.

Подобається це:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

Приклади

№1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

№2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

№3:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

№4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

ПРИМІТКА. Просто для того, щоб зрозуміти, що там, де перенаправлення відображається в командному рядку, немає ніякої різниці, оскільки sshвиклик віддаленої оболонки з об'єднанням її аргументів так чи інакше, цитування не має великої різниці, за винятком випадків, коли вам потрібно цитувати на віддаленій оболонці як у прикладі №4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>

4
ти геній! Що мені потрібно зробити, щоб досягти вашого рівня? У мене вирішено багато роботи. Дуже дякую.
AllenD

14
@AllenD - просто продовжуйте задавати питання та намагайтеся брати участь на сайті стільки, скільки зможете. Я завжди намагаюся і щодня дізнаюся щось нове. До вашого запитання я також не знав, як це зробити. 8-). Дякуємо за запитання!
slm

5
зауважте, що перенаправлення може з’явитися в будь-якій точці команди: наприклад, bash -s -- --time bye < ./ex.bashабо навіть < ./ex.bash bash -s -- --time bye. це тому, що оболонка спочатку виймає інструкцію про переадресацію (незалежно від того, де вона знаходиться в команді), потім встановлює перенаправлення, а потім виконує решту командного рядка з перенаправленням на місці.
lesmana

@sim Я намагаюся зробити це саме те саме, але зсередини сценарію, а не з командного рядка. Будь-яка ідея, як це зробити? Чомусь вкладати точну відповідь у беккетки взагалі не працює. Замість цього він запускає скрипт, вказаний локально, і вихід надсилається як команда bash over ssh
krb686

@ krb686 - Я б запитав це як новий Q.
slm

5

Про поводження з довільними аргументами

Якщо ви дійсно використовуєте лише один рядок, тобто -time Aug 18 18, тоді ви можете просто жорсткий код, і наявні відповіді підказують, як це зробити адекватно. З іншого боку, якщо вам потрібно передати невідомі аргументи (наприклад, повідомлення, яке відображатиметься в іншій системі, або ім’я файлу, створеного там, де кінцеві користувачі можуть контролювати його ім’я), тоді потрібно більше уваги.


З bashабо kshяк/bin/sh

Якщо ваш пульт /bin/shнадається bash або ksh, ви можете сміливо виконувати наступні дії з ненадійним списком аргументів, таким чином, що навіть шкідливі імена (наприклад $(rm -rf $HOME).txt) можуть бути передані як аргументи безпечно:

runRemote() {
  local args script

  script=$1; shift

  # generate eval-safe quoted version of current argument list
  printf -v args '%q ' "$@"

  # pass that through on the command line to bash -s
  # note that $args is parsed remotely by /bin/sh, not by bash!
  ssh user@remote-addr "bash -s -- $args" < "$script"
}

З будь-яким сумісним POSIX /bin/sh

Щоб бути захищеним від досить зловмисних даних аргументів (намагання скористатись цитуванням, що не відповідає POSIX, використовуваним printf %qу bash, коли недруковані символи присутні у рядку, що виводиться), навіть із тим, /bin/shщо є базовою лінією POSIX (наприклад, dashабо ash), це виходить трохи цікавіше:

runRemote() {
  local script=$1; shift
  local args
  printf -v args '%q ' "$@"
  ssh user@remote-addr "bash -s" <<EOF

  # pass quoted arguments through for parsing by remote bash
  set -- $args

  # substitute literal script text into heredoc
  $(< "$script")

EOF
}

Використання (для будь-якого з перерахованих вище)

Функції, наведені вище, можуть бути викликані як:

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

... або ...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"

-3

Скажімо, aa - це локальний файл, що містить ls

$ssh servername "cat | bash" < a.a

змініть 127.0.0.1 на будь-який ваш віддалений ip

ці двоє дають повідомлення про розподіл псевдоти, але вони працюють.

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

Або

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a


2
Я намагаюся бачити, наскільки це відповідає на питання.
ChrisWue

Якість та форматування сумнівні. Я не бачу жодної нової корисної інформації, яка також відсутня у прийнятій відповіді.
Джулі Пелтьє

@JuliePelletier Я наводив кілька «котячих» прикладів не у прийнятій відповіді. Добре знати альтернативні способи ведення справ.
барлоп

Це не дуже добре; ваші коти марні.
Скотт

2
О Боже. Я залишив посилання на марне використання кота, тому що я припускав, що до цього часу всі принаймні чули про цю фразу; мабуть, це було поганим припущенням з мого боку.
Скотт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.