Я пытаюсь добавить многострочный текст, содержащий несколько одинарных кавычек ('), к файлу, который находится на другом компьютере и к которому можно получить доступ только через другого пользователя. Вот мой фрагмент кода:
element_list=("element1" "element2")
for element in ${element_list[@]}
do
read -r -d '\n' CONTENT << EOM
field1 = on
field2 = '$element'
field3 = '$element-random-text'
EOM
CONFIG_FILE=/tmp/config.txt
sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c 'echo \"$CONTENT\" >> $CONFIG_FILE'"
done
Хотя скрипты выполняются успешно, одинарные кавычки, присутствующие в значениях field2 и field3, исчезают. Вывод, добавленный к файлу, выглядит так:
field1 = on
field2 = element1
field3 = element1-random-text
field1 = on
field2 = element2
field3 = element2-random-text
Я хочу, чтобы эти одинарные кавычки тоже были сброшены в файл. Ожидаемый результат:
field1 = on
field2 = 'element1'
field3 = 'element1-random-text'
field1 = on
field2 = 'element2'
field3 = 'element2-random-text'
Любая помощь будет оценена по достоинству.
Примечание. Необходимо выполнить эту команду с другого компьютера и с использованием другого_пользователя (не vm_user).
Такое смешивание команд ssh и sudo будет сложным, потому что требуется так много уровней цитирования, и они не вложены чисто.
Правильно @Barmar, но это требование. Я не могу выполнить этот скрипт на той же машине, и только other_user может писать в CONFIG_FILE.
Обязательно ли делать это с echo? Разве вы не можете скопировать содержимое в виде файла на удаленную машину?
Я должен добавить к существующему файлу, присутствующему на другой машине. Существующий файл не может быть полностью перезаписан.
Я никогда не говорил иначе. scp filename remote:/tmp/new; sudo other_user "cat /tmp/new >> $CONFIG_FILE"
Научитесь проверять свой код на shellcheck.net. Если это не исправит, используйте обновленный код в своем вопросе. Удачи.





Гораздо более простое решение — выполнить все расширение локально, а затем просто записать результат в конец конвейера.
config_file=/tmp/config.txt
element_list=("element1" "element2")
for element in "${element_list[@]}"
do
read -r -d '\n' content <<____EOM
field1 = on
field2 = '$element'
field3 = '$element-random-text'
____EOM
echo "$content"
done |
sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c \"cat >> '$config_file'\""
Захват документа здесь только для того, чтобы вы могли сразу же echo это, очевидно, пустая трата памяти; Я полагаю, что ваше настоящее тело петли выглядит более сложным.
Не используйте верхний регистр для своих личных переменных; см. Правильный ввод переменных в сценариях Bash и shell.
Для надежности я также добавил двойные кавычки вокруг ${element_list[@]}; см. Когда заключать в кавычки переменную оболочки
Спасибо, это было полезно. Дополнительное изменение, которое потребовалось, заключалось в заключении команды sudo su - other_user -c "cat >> '$config_file'" в двойные кавычки. Итоговая команда выглядела так: sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c \"cat >> '$config_file'\""
Я удалил ненужные кавычки вокруг команды sudo su, чтобы упростить командную строку. В команде нет метасимволов оболочки, поэтому ssh с радостью позволит вам уменьшить цитирование.
Сначала я пробовал без кавычек, но это выдало эту ошибку: bash: /tmp/config.txt: Permission denied. Хотя заключение всей команды в двойные кавычки исправляет это. Может быть, это потому, что я использовал ssh -t
Аааа, я вижу, команду sudo нужно заключать в кавычки отдельно, чтобы удаленная оболочка не пыталась добавить файл до получения привилегий. Я обновлю ответ - спасибо за отзыв!
Одинарные кавычки соответствуют
'передecho.