Здравствуйте, люди мира,
Я пытаюсь написать скрипт, который позволит пользователю переключать приложения между сайтами в bash.
Нашими приложениями управляет Pacemaker, и я подумал, что смогу написать функцию, которая будет принимать необходимые переменные и действовать. Остановитесь на одном сайте, начните на другом. После того, как я перешел к удаленному компьютеру с помощью ssh
, я не могу вернуть значение команды grep
/awk
для статуса приложения в PCS.
Я столкнулся с несколькими проблемами и пробовал ответы на stackoverflow и других сайтах.
ssh
в /dev/null 2>&1
, когда на экране появляются баннеры, которые администратор unix имеет для локального пользователя, и -q
не имеет с этим дело. Это останавливает возврат чего-либо?awk '{print \\\\\\$4}'
в коде я получаю ошибку "обратная косая черта не последний символ в строке"result=$(sudo pcs status | grep nds_$resource)
, однако это привело к ошибке пароля на sudo
>/dev/tty and >$(tty)
ssh
(удалить /dev/null 2>&1
) и поместить вывод в переменную при вызове функции, удалив awk
из записи sudo pcs status
.result=$(pcs_call "$site1" "1" "2" "disable" "pmr")
echo $result | grep systemd
Это было нормально, но когда я добавил | awk '{print \\\$4}'
, я получил четвертое слово в баннере.
Любая помощь будет оценена по достоинству, так как я занимаюсь этим уже несколько дней.
Я смотрел этот ответ от Бруно, но не знаю, как реализовать, поскольку у меня есть несколько sudo
команд.
Ниже приведен мой код функции для тестирования на одной машине;
site1=lon
site2=ire
function pcs_call()
{
site=$1
serverA=$2
serverB=$3
activity=$4
resource=$5
ssh -tt ${site}servername0${serverA} <<SSH > /dev/null 2>&1
sudo pcs resource ${activity} proc_${resource}
sleep 10
sudo pcs status | grep proc_$resource | awk '{print \\\$4}' | tee $output
exit
SSH
echo $output
}
echo ====================================================================================
echo Shutting Down PMR in $site1
pcs_call "$site1" "1" "2" "disable" "pmr"
3 обратных слэша таковы, что awk захватит четвертый символ. Если я их не использую, то будет использоваться четвертая переменная, переданная из начальной функции, например, awk '{print disabled}'
Я бы посоветовал начать с вставки всего этого в ShellCheck.net и исправления ошибок до тех пор, пока не останется предложений, но здесь есть некоторые серьезные проблемы, с которыми shellcheck не сможет справиться в одиночку.
> /dev/null
говорит: «Выбрасывайте в битбакет все возвращаемые данные. 2>&1
говорит: «Отправляйте любые полезные отчеты об ошибках на stderr, куда бы ни направлялся stdout». Ваш первоначальный оператор, предназначенный для извлечения информации из удаленной системы, немедленно отбрасывает ее. Если вы не просто хотите, чтобы в удаленной системе произошло что-то, о чем вы не хотите знать больше локально, вы тратите свое время на что-либо после этого, потому что вы сбросили все, что он должен был сказать.awk
, чтобы процитировать знак доллара на $4
.sudo
в удаленной системе, это не сработает для вас. Я думаю, нам нужно больше информации об этом, прежде чем мы обсудим это глубже.ssh
передает все в /dev/null
, ничто внутри передаваемого блока кода не даст вам никаких результатов в вызывающей системе.$output
, но похоже, что вы намереваетесь установить tee
? Так не бывает . Аргумент tee
— это имя файла, в который он ожидает записать копию данных, которые также передаются на стандартный вывод (т.е. как в «Т»-соединении, в сантехнике), но НЕ присваивает переменные.(Кроме того, вы еще даже не используете serverB, но вы можете добавить его обратно, когда преодолеете текущие проблемы.)
В конце вы echo $output
, который, вероятно, пуст, так что в основном это просто echo
, который не будет отправлять ничего, кроме новой строки, которая будет просто отправлена обратно на исходный сервер и сброшена в /dev/null
, так что все это бессмысленно... .
Давайте убирать
sudo pcs status | grep proc_$resource | awk '{print \\\$4}' | tee $output
а попробуй немного по другому, да?
Во-первых, я предполагаю, что у вас нет пароля sudo
, в противном случае будет совершенно другой разговор, чтобы решить это.
Во-вторых, как правило, использование в конвейере как grep
, так и awk
является антипаттерном, так как они оба по своей сути являются механизмами регулярных выражений. Выбери один. Если вы можете заставить grep
делать то, что хотите, это довольно эффективно. Если нет, awk
очень гибкий. Пожалуйста, прочтите страницы документации по используемым вами инструментам, если что-то не работает. Быстрый поиск «bash man grep» или «awk manual» быстро даст вам отличные ресурсы, и они вам понадобятся, если вы пытаетесь сделать что-то настолько сложное.
Итак, давайте посмотрим на переделку, сделав некоторые предположения...
function pcs_call() {
local site = "$1" serverA = "$2" activity = "$3" resource = "$4" # make local and quotes habits you only break on purpose
ssh -qt ${site}servername0${serverA} "
sudo pcs resource ${activity} proc_${resource}; sleep 10; sudo pcs status;
" 2>&1 | awk -v resource = "$resource" '$0~"proc_"resource { print $4 }'
}
pcs_call "$site1" 1 disable pmr # should print the desired field
Если вы хотите записать данные в переменную для последующего использования -
var1 = "$( pcs_call "$site1" 1 disable pmr )"
Отвечая на ваш вопрос, используйте $(seq 1 10)
или просто {1..10}
.
ssh -qt chis03 '
for i in {1..10}; do sudo pcs resource disable ipa $i; done;
sleep 10; sudo pcs status;
' 2>&1 | awk -v resource=ipa '$0~"proc_"resource { print $2" "$4 }'
Сначала он сообщает о awk
, потому что порядок элементов в конвейере «не определен», но стандартный вывод ssh
подключен к стандартному выводу awk
(и, поскольку он был заменен на стандартный вывод, то же самое относится и к стандартному выводу), поэтому они работает асинхронно/одновременно.
Да, поскольку они используют литералы, одинарные кавычки проще и эффективнее «лучше». Если абстрагироваться с помощью vars, это не сильно изменится, но переключитесь обратно на двойные кавычки.
# assuming my vars (svr, verb, target) preset in the context
ssh -qt $svr "
for i in {1..10}; do sudo pcs resource $verb $target \$i; done;
sleep 10; sudo pcs status;
" 2>&1 | awk -v resource = "$target" '$0~"proc_"resource { print $2" "$4 }'
Это помогает?
Привет Павел, Спасибо, что нашли время, чтобы прочитать это.
Решение сработало 1) Да, я думал, что /dev/null подавит ВСЕ выходные данные, однако я видел текст из удаленной оболочки. Это потому, что я использовал EOF (SSH в моем сценарии), поэтому мне нужно было иметь \\\$ 4 в awk. 2) Спасибо за информацию о тройнике, я бы увидел, что я создавал файлы в папке, из которой я запускал скрипт, с выводом скрипта. 3) спасибо за совет по grep/awk - именно так я использовал эту команду в течение многих лет, я постараюсь улучшить свой awk. 4) да sudo был без пароля 5) serverB в другой части скрипта не выложил.
Привет, Пол. Разрешает ли этот метод, в отличие от heredoc, эту команду; ``` для i в seq 1 10
; отключить ресурс sudo pcs ipa \$i; сделанный; спать 10; статус sudo ПК; " 2>&1 | awk -v resource=ipa '$0~"proc_"resource { print $2" "$4 }' ``` Это не позволяет мне запускать его, у меня есть несколько приложений, работающих на одном сервере
Команда awk выполняется перед циклом for. ++ awk -v resource=ipa '$0~"pcs_"resource { print $2" "$4 }' +++ seq 1 10 ++ ssh -qt chis03 ' '\''for i in 1 2 3 4 5 6 7 8 9 10; отключите ресурс sudo pcs ipa_; сделанный; спать 10; статус sudo pcs;'\'' '
Решение: используйте одинарные кавычки вместо двойных. это потому, что я не передаю внешнюю переменную, поэтому мне не нужно ее сохранять, просто нужно использовать внутреннюю переменную для команды. ssh -qt ${site}server${serverA} 'для i в $(seq 1 10); отключите ресурс sudo pcs ipa_$i; сделанный; спать 10; статус sudo ПК; ' 2>&1 | awk -v resource=ipa '$0~"pcr_"resource {print $2" "$4}"
Между прочим, нет ничего плохого в использовании вот этого документа. Мне просто нравятся простые кавычки, но если вам нужны как одинарные, так и двойные кавычки в вашем коде, here-doc — хороший способ разрешить и то, и другое! Хорошо добавлять инструменты в набор инструментов, если вы понимаете их и эффективно используете. Строка здесь — еще одна, которую я часто использую, но опять же, здесь она не нужна.
Почему в команде
$4
передawk
используются символы обратной косой черты?