Вставка некоторых последовательных команд в терминал останавливается на командах с пользовательским вводом, например:

read VAR
echo $VAR

Или

select VAR in 1 2 3; do break; done
echo $VAR

echo $VAR не вставляется/не выполняется.

Однако наличие всех команд в одной строке работает:

read VAR; echo $VAR

Но это не является предпочтительным, если за ним следует больше команд.


Почему это так и как это обойти?

В моем случае в сервисной документации есть повторяющиеся команды.
Я мог бы, конечно, написать сценарий, но это не то, что я собираюсь делать, и это может быть невозможно в системах с доступом только для чтения.

3
Anderson 19 Июл 2018 в 19:35
Не вставлять шелл-код в терминал, а поместить его в скрипт и запустить как обычно?
 – 
Kusalananda
19 Июл 2018 в 18:25
2
Как я уже сказал, это не вариант здесь.
 – 
pLumo
19 Июл 2018 в 18:27
 – 
JoL
20 Июл 2018 в 01:43
Спасибо за подсказки, связанные с безопасностью. Я полностью осознаю это. Для моего варианта использования я думаю, что это должно быть хорошо, так как это просто документация для моего собственного сервиса для меня и оператора.
 – 
pLumo
20 Июл 2018 в 11:03

4 ответа

Лучший ответ

Очень удобным способом является следующий:

Просто введите в терминал следующее:

( paste-your-multiline-script-here ) введите

Подробное описание:

  1. В терминале вы начинаете с (

    Необязательно: нажмите enter (только для форматирования)

  2. Теперь вы можете вставить несколько строк

    например:
    echo hello
    echo world

    Альтернатива: вы вводите/вставляете строку за строкой (заканчивая каждую клавишей enter).

  3. Наконец, введите завершающий ) и снова нажмите enter, что приведет к выполнению всех вставленных/введенных строк.

Небольшой рабочий пример (для вставки построчно с помощью enter):

anderson@tp ~ % (
\`subsh> echo hello
\`subsh> echo world
\`subsh> )
hello
world
anderson@tp ~ % 

Небольшой рабочий пример (для вставки всего скрипта):

anderson@tp ~ % (
\`subsh> echo hello
echo world
\`subsh> )
hello
world
anderson@tp ~ %

Небольшой рабочий пример без форматирования (для вставки всего скрипта):

anderson@tp ~ % (echo hello                                                
echo world)
hello
world
anderson@tp ~ % 
7
Anderson 19 Июл 2018 в 18:43
1
Это работает. Вам даже не нужно нажимать ввод, только в конце.
 – 
pLumo
19 Июл 2018 в 18:15
Да, я пытался прояснить это. Я переформулирую его в лучшую сторону. :) Удачной оклейки. ;)
 – 
Anderson
19 Июл 2018 в 18:16
1
Это также работает при вставке всего: ( read VAR \n echo $VAR )
 – 
pLumo
19 Июл 2018 в 18:18
Конечно, это было только из соображений форматирования. :)
 – 
Anderson
19 Июл 2018 в 18:22
2
Я имею в виду, что вставка, включая ( и ), работает
 – 
pLumo
19 Июл 2018 в 18:23

Когда вы вставляете следующие две команды в оболочку:

read VAR
echo $VAR

... первый сообщает оболочке прочитать строку текста в переменную с именем VAR. Вы указываете это значение в следующей строке; это просто команда, которая, как вы думали, будет выполнена.

Выведите значение переменной VAR, и вы увидите:

$ printf '%s\n' "$VAR"
echo $VAR

То же самое происходит с меню select.

Я бы посоветовал, если ваша документация/команды ожидают, что пользователь введет значение, вы вставите комментарий на этот счет:

read VAR

(Пользователь вводит значение)

echo $VAR
5
Jeff Schaller 19 Июл 2018 в 17:52
Спасибо за объяснение. Имеет смысл для меня. Что вы подразумеваете под "вставить комментарий"? Вы имеете в виду, что я должен сказать оператору скопировать и вставить все команды до ввода пользователем, а затем скопировать и вставить остальные?
 – 
pLumo
19 Июл 2018 в 17:58

Вы можете получить эту работу так, как хотите, именно так, как вы это делали. Я все время это делаю.

Если бы вы использовали zsh и терминал, который заключает свои вставки в скобки специальными escape-последовательностями, такими как urxvt, по умолчанию он уже работал бы так, как вы хотели. Если вы используете bash, вам просто нужно активировать его интерпретацию скобок вставки, выполнив bind 'set enable-bracketed-paste on'. Затем он будет ждать, пока вы нажмете Enter, прежде чем выполнить то, что вы вставили. В этом отношении разница между bash и zsh заключается в том, что bash будет разделять команды, которые вы вставили в историю, так что для 2 строк вам нужно будет нажать Up, Up, Enter, Up, Up, Enter, в то время как zsh сохраняет команды вставлены сгруппированы как один в истории независимо от того, сколько строк, Вверх, Ввод.

Больше об этом написано в следующих ответах. Второй мой и включает в себя таблицу терминалов, поддерживающих вставку в скобках. Если вы в конечном итоге используете urxvt, я рекомендую установить расширение, которое я включил в ответ, чтобы избежать уязвимости, о которой был вопрос:

https://security.stackexchange.com/a/52655/132634

https://security.stackexchange.com/a/184112/132634

РЕДАКТИРОВАТЬ: Кстати, просто чтобы быть более точным на случай, если вы пропустили это, если вы этого не делаете (используя вставку в скобках), вы открыты для внедрения кода оболочки при вставке с веб-сайтов. Веб-сайты могут, в конце концов, скрывать код всеми возможными способами и заставлять вас копировать его без вашего ведома.

Проверьте этот сайт, чтобы узнать, уязвимы ли вы:

http://thejh.net/misc/website-terminal-copy-paste

Похоже, вы будете выполнять:

git clone git://git.kernel.org/pub/scm/utils/kup/kup.git

Когда на самом деле вы будете запускать что-то вроде этого (я удалил непечатаемый управляющий байт):

git clone [201~/dev/null; clear; echo -n "Hello ";whoami|tr -d '\n';echo -e '!\nThat was a bad idea. Don'"'"'t copy code from websites you don'"'"'t trust!
Here'"'"'s the first line of your /etc/passwd: ';head -n1 /etc/passwd
git clone git://git.kernel.org/pub/scm/utils/kup/kup.git 
1
JoL 20 Июл 2018 в 01:39

Это можно сделать, поместив \ в конце каждой строки перед ее копированием.

3
Anderson 19 Июл 2018 в 19:13
1
Добавление ;\ действительно работает. Но это весьма раздражает...
 – 
pLumo
19 Июл 2018 в 17:53