Попытка удаленно получить хэш файла с другого Linux-сервера

В ответах на:

I want to write the whole output to the file, a copy of the original with the changes made.

Вы можете либо перенаправить на файл, например

sed '4{ s/fox/elephant/; s/dog/cat/}' infile > modified_file

Или изменить в -место с флагом -i:

sed -i '4{ s/fox/elephant/; s/dog/cat/}' infile

... или сделайте резервную копию исходного файла и запишите изменения с тем же именем исходного файла.

sed -i.backup '4{ s/fox/elephant/; s/dog/cat/}' infile

Или командой w:

sed '4{ s/fox/elephant/; s/dog/cat/ }; w modified_file' infile

Если вы хотите написать только те строки, что sподстановка команд прошла успешно (, а это не то, о чем вы просите в настоящее время ), с помощью флага wвы можете сделать:

sed '4{ s/fox/elephant/; s/dog/cat/w modified_file
}' infile
0
28.12.2020, 22:34
2 ответа

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

Оболочка — это интерпретатор командной строки. Его основная цель состоит в том, чтобы выполнять команды с учетом командных строк (командные строки, которые являются другим способом сказать код в синтаксисе оболочки ), который вы ему даете. В оболочке Korn -, подобной вашей, со значением $FILENAME, равным File Name With Spaces.mp4, и командной строкой типа:

 ssh server md5sum filelocation/"${FILENAME}"

Задача оболочки состоит в том, чтобы выполнить найденный в $PATHфайл с именемssh(что-то вроде/usr/bin/ssh)с этими аргументами:

  • argv[0]:ssh
  • argv[1]:server
  • argv[2]:md5sum
  • argv[3]:filelocation/File Name With Spaces.mp4

В синтаксисе языка оболочки аргументы команды разделяются пробелом, $xxxзапускает раскрытие параметра, а кавычки здесь используются для предотвращения разделения и подстановки при таком расширении.

Затем задача sshсостоит в том, чтобы из полученного списка аргументов соединиться с server, соединить оставшиеся аргументы пробелами,и передать результат в оболочку входа удаленного пользователя (их предпочтительную оболочку, которую они могут изменить с помощью chsh, zshдля меня, но может быть tcsh, fish, yash, bash, rc... ), выполнив его с аргументами:

  • argv[0]:имя этой оболочки
  • argv[1]:-c
  • argv[2]:что -результат, так вот:md5sum filelocation/File Name With Spaces.mp4

Здесь, несмотря на то, что все оболочки имеют разный синтаксис, эта командная строка достаточно проста, чтобы большинство интерпретировало ее одинаково. То есть он выполнит команду /path/to/md5sumс этими аргументами:

  • argv[0]:md5sum
  • argv[1]:filelocation/File
  • argv[2]:Name
  • argv[3]:With
  • argv[4]:Spaces.mp4

Чтобы команда md5sumзапускалась с одним аргументом filelocation/File Name With Spaces.mp4, нам нужно сообщить этой удаленной оболочке, что эти пробелы не следует использовать в качестве разделителей аргументов. И это делается с помощью цитирования/экранирования. И синтаксис цитирования значительно различается между оболочками.

В любом случае пробел — не единственный символ, который может вызвать проблемы. Любой символ, являющийся специальным в синтаксисе удаленной оболочки, также будет проблемой. Например, если бы имя файла было $(reboot).mp4или blah;rm -rf ~;blah.mp4, у вас были бы большие проблемы.

Если вы знаете, что удаленная оболочка похожа на -Борна, вы можете сделать:

#! /bin/zsh -
while IFS=, read -ru3 location user md5 file rest; do
  md5sum -- $file | read check rest
  filename=$file:t
  print -r -- $filename
  ssh -n server "md5sum filelocation/${(qq)filename}" | read remotecheck rest
  if [[ $md5 = $check ]]; then
    printf '%s File MD5: %s\n' Local "$check" Remote "$remotecheck"
  fi
done 3< $path_to_file

Это ${(qq)file}кавычки с одинарными кавычками, что является самым безопасным способом заключать в кавычки такие вещи в Bourne -, как оболочки . Так что в вашем случае File Name With Spaces.mp4будет передано как 'File Name With Spaces.mp4'. Если бы это было File Name With Quote's.mp4, это было бы 'File Name With Quote'\''s.mp4', где все цитируется с '...', кроме самого ', которое цитируется с \.

Если вы не можете гарантировать, что удаленная оболочка будет похожа на -Борна, см. Как выполнить произвольную простую команду через ssh, не зная оболочки входа удаленного пользователя? для получения дополнительных опций.

Здесь, для вашего конкретного случая использования -, чтобы сравнить локальную и удаленную контрольные суммы,другой вариант - использовать режим проверки md5sum-c):

#! /bin/zsh -
while IFS=, read -ru3 location user md5 file rest; do
  (cd -P -- $file:h && md5sum -- $file:t) |
    ssh -n server 'cd./filelocation && md5sum -c'
done 3< $path_to_file

На этот раз имя файла записывается локальным md5sumи читается удаленным на его стандартном вводе, поэтому нам не нужно заключать его в кавычки для удаленной оболочки. И эта командная строка cd./filelocation && md5sum -cпонимается большинством оболочек (префикс ./предназначен для того, чтобы избежать эффекта $cdpath/ $CDPATHв csh/tcsh/bash, оболочках, которые делают или могут читать свой файл rc при вызове не -в интерактивном режиме или через ssh ).

3
18.03.2021, 22:40

Проблема заключается в этой строке и в том, как ее интерпретируют две оболочки.

REMOTECHECK=$(ssh server md5sum filelocation/"${FILENAME}" < /dev/null | awk '{ print $1 }')

Давайте предположим, что имя файла "счастливый понедельник", и мы рассмотрим конкретно команду ssh

После оценки значения переменной локальная оболочка увидит это

ssh server md5sum 'filelocation/happy monday' < /dev/null

В частности, кавычки удаляются, и оболочка обрабатывает содержимое как одно слово, filelocation/happy monday.

Результат теперь выполняется sshи аргументы командной строки передаются в удаленную оболочку (независимо от того, что это может быть ). Помните, что кавычки были удалены, так что это то, что выполняется удаленно:

md5sum расположение файла/счастливого понедельника

На данный момент md5sumищет два файла, filelocation/happyи monday.

Для предотвращения потери кавычек необходимо заключить всю команду в другой набор

ssh server "md5sum 'filelocation/happy monday'"

Повторное применение этого к исходному коду,

REMOTECHECK=$(ssh -n server "md5sum 'filelocation/$FILENAME'" | awk '{ print $1 }')
0
18.03.2021, 22:40

Теги

Похожие вопросы