Использовать here-document в однострочном тексте?

Использовать here-document в однострочном тексте?

У меня есть простой скрипт, который выполняет команды на удаленном хосте, используя sshhere-document.

Я пытался сделать это с помощью однострочного командного файла, но не мог понять, как сделать here-document вне скрипта. Возможно ли это? Я потратил некоторое время на гугление и чтение документации о here-documents, но ничего не получалось.

Этот скрипт работает отлично — мне нужен был раздел here-document для awkудаленного запуска через ssh, но я обычно предпочитаю писать однострочники для простых вещей:

#!/bin/bash
# it looks up all my hosts with 'db' in the name
# then gets the PID of any rsyncs running as user 'research'
# and pumps them into xargs

getHosts=(`curl --silent "http://assetts.lab/all_hosts" | grep -v ^# | awk -F" " '{print$1}'|grep db`)
for BOX in ${getHosts[@]};do
    echo "$BOX: "
    ssh -T sshUser@$BOX <<"EOF"
ps -ef | egrep "rsync|iasync" | awk -F" " '{if ($1 ~ "research") print $2}'|sudo xargs -i ps -fp '{}'
#ps -ef | egrep "rsync|iasync" | awk -F" " '{if ($1 ~ "research") print $2}'|sudo xargs -i kill '{}'
EOF
    echo
done

Я, наверное, упускаю что-то простое... В любом случае, спасибо за любые предложения :)

решение1

Я не вижу необходимости что-либо делать с использованием документа here-document, но яделатьвидите, что вы можете значительно упростить другие вещи в своем скрипте (что, в свою очередь, делает here-document устаревшим).

Прежде всего, конвейер для заполнения вашего getHostsмассива может быть упрощен (редко возникает необходимость grepв конвейере awk), а весь массив можно удалить:

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
while IFS= read -r remote; do
   # rest of code
done

Здесь я объединил вашу команду grep++ в одну команду. Я также позволил команде напрямую передавать имена хостов в цикл, а не сохранять их в промежуточной переменной awk.grepawkawk

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

Лучше всего это сделать с помощью pgrep:

pgrep -l -U research 'rsync|iasync'

Чтобы обозначить эти процессы, используйте pkillвместо pgrepи опустите -lопцию.

Полный сценарий будет выглядеть так:

#!/bin/sh

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
while IFS= read -r remote; do
   printf 'Processing host "%s"\n' "$remote"
   ssh "$remote" 'pgrep -l -U research "rsync|iasync"'
done

Или, используя xargs:

#!/bin/sh

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
xargs -I {} sh -c '
   printf "Processing host \"%s\"\n" "$1"
   ssh "$1" "pgrep -l -U research \"rsync|iasync\""' sh {}

Если вы xargsэто поддерживаете, то можно запустить несколько sh -cпроцессов одновременно с помощью -P n, где n— количество одновременно выполняемых sh -cкоманд .xargs

решение2

Функция EOF в bash в основном предназначена для использования так, как вы это делаете в своем примере, то есть для отправки нескольких строк текста другой команде.

Если вы хотите, чтобы это было однострочным, то EOF придется убрать.

Чтобы выполнить команду на удаленном хосте с помощью ssh, вам нужно сделать следующее:

ssh host command

Например:

ssh host "ls -alh"

выполнит команду на хосте и вернет вывод на консоль.

Ваш пример кода можно было бы переписать в одну строку, если бы вы обратили внимание на то, как вы используете кавычки, например так:

ssh host "ps -ef | egrep 'rsync|iasync' | awk -F' ' '{if (\$1 ~ \"research\") print \$2}'"

Эта строка в двойных кавычках помещает аргументы отдельных команд в одинарные кавычки. Когда требуется больше двойных кавычек (шаблон "research"), их нужно экранировать с помощью \, и то же самое касается $символов.

Связанный контент