Мой собственный ответ, после изучения ответа и комментария автор icarus :
Вы должны различать «новую строку в файле» и «новую строку в консоли». В консоли истинным символом новой строки является CRLF, что противоречит интуиции, как мы увидим ниже.
В контексте UNIX в текстовых файлах LF означает перевод строки, и наоборот, вы подразумеваете перевод строки под LF. (Под «вы имеете в виду» я имею в виду текст на естественном языке.) В DOS CR + LF и так далее. Ok. Все это знают.
(Unix) консоль более сложная. Сначала вы должны помнить, что LF и CR являются управляющими кодами, т.е. могут использоваться для управления консолью, например выделение полужирным шрифтом, цветом и т. д.
Если вы введете LF (\ n, перевод строки) в консоль, вы получите новую строку. Уловка состоит в том, что два улова таковы: (1) консоли, так сказать, двухслойные; они состоят из фильтра и части рендеринга. (Специальная номенклатура.) Скрытый (для обычных пользователей) фильтр переводит LF в CRLF. (2) Средству визуализации нужен CRLF (\ r \ n) для новой строки в обычном смысле. Подробнее см. Ниже.
Машинописный файл, созданный командой script (1)
, записывает символы после фильтрации ввода в консоль. Вот почему символы новой строки в машинописном тексте - это CRLF.
Подробности и разное. факты:
$ stty -opost
и стереть его с помощью $ stty opost
. "opost" - это аббревиатура от "POST-обработка вывода".
opost
выполняет LF-> LFCR, когда установлено onlcr
. Когда установлено onocr
, CR будет удален в начале строки и т. Д. Ссылка: POSIX, глава 11 « Общий интерфейс терминала ». man 4 console_codes
объясняет, что «ESC D» (\ eD) означает перевод строки, а «ESC E» (\ eE) - перевод строки. Если вы их распечатаете, «ESC D» будет «перемещать курсор вниз», а «ESC E» - CR + LF, независимо от ± opost-ness. Для экспериментов рекомендую писать с отдельной консоли. Например, $ echo -ne '1st \ n2nd \ r \ n3rd \ n "> / dev / tty1
записывает в первую консоль, отличную от X, а / dev / pts / 0
это первый X-терминал.Это не самый удобный способ, но и наименее неоднозначный.
Вы говорите оболочке на другом компьютере, что нужно использовать файл ./ variables
, который отсутствует в pwd
этой оболочки. Пошагово это выглядит так:
Эта команда подключается через ssh и отправляет строки из локального test.sh
ssh -i "auth.key" user @ host 'bash -s' < test.sh
Удаленные оболочки запускаются соединением ssh
, а затем получают следующие строки:
#! / bin / bash
Интерпретация этого строка удаленной оболочки зависит от того, что это за оболочка. Большинство командных интерпретаторов рассматривают эту строку как комментарий. Если оболочка - sh
, удаленная оболочка не станет bash
, потому что строка shebang действительна только в файлах сценария, а сценариям необходимо установить исполняемый бит. source ./variables.txt
Теперь удаленной оболочке указывается источник из файла variables.txt
в текущем рабочем каталоге. Если файла нет, оболочка выдаст ошибку. В вашем случае оболочка - это Bash, и ошибка:
bash: строка 2: ./variables.txt: нет такого файла или каталога
echo $ name
Потому что $ name
пусто, в терминале печатается только пустая строка. Чтобы убедиться в этом сами, поместите файл variables.txt
в удаленный домашний каталог с другой строкой источника, скажем:
name=remotehost
И запустите свой тестовый скрипт, как раньше.
Программы, запущенные на удаленном компьютере, видят файлы на удаленном компьютере, а не файлы на компьютере, с которого вы запустили ssh
. Вы говорите SSH скопировать содержимое test.sh
на удаленный компьютер и передать его в качестве входных данных в bash
там, поэтому у вас не возникнет проблем с запуском test.sh
. Но когда сценарий (который bash получает на стандартный ввод) пытается прочитать variables.txt
, он ищет его на машине, на которой он выполняется (это не так, как если бы у него был выбор), и не не найти.
Если ваш сценарий не слишком сложен и в нем нет вложенных включений, вы можете выполнить замену текста, чтобы встроить содержимое сценария. Обратите внимание, что это ненадежно - это работает только в том случае, если source ./variables.txt
отображается непосредственно в скрипте, а не в том случае, если он включает сложные кавычки, переменные, eval
и т. Д. Для простоты я Предположим, что команда source
находится одна в своей строке. Для более сложных сценариев можно было бы справиться с более сложными преобразованиями.
<test.sh sed '/^[ \t]*source variables\.txt[ \t]*$/ {
d
r variables.txt
}' | ssh -i "auth.key" user@host 'bash -s'