find -name \*.log -print0 |
xargs -0 sh -c 'for i; do head -n 500 $i | fgrep -q myip && echo $i; done
Это найдет все имена файлов, оканчивающиеся на .log
, и передаст этот список в xargs
. -print0
и xargs -0
обычно используются для использования нулевого байта для завершения имен файлов, для защиты имен файлов, содержащих пробелы (нулевой байт никогда не может использоваться в имени файла, поэтому он является безопасным разделителем ).
xargs
запустит команду, указанную после xargs
, и ее аргументы с таким количеством имен файлов, которое поместится за один вызов команды. В этом случае дана командаsh
(оболочка ), и этой оболочке дается небольшой сценарий оболочки для запуска.
Сценарий оболочки в основном:
for i; do
head -n 500 $i | fgrep -q myip && echo $i
done
Часть for i
перебирает все аргументы, переданные оболочке, то есть все имена файлов. Для каждого имени файла занимает первые 500 строк,и ищет заданную строку. fgrep -q
означает, что fgrep останавливается, как только строка найдена; если строка найдена, присваивается статус выхода «успех», в противном случае — «неудача». Наконец, && echo $i
означает, что если предыдущая команда имеет статус «успешно», выполняется эхо, что означает, что имя файла отображается, если строка найдена.
Сначала вы подключаете основное соединение без переадресации портов:
ssh -NMS /path/to/socket user@server
/path/to/socket
зависит от вас. Там будет создан сокет. В скрипте вы хотите использовать -f
.
Затем вы используете -S /path/to/socket -O …
для управления главным соединением. Например. вы можете проверить, работает ли он еще:
ssh -S /path/to/socket -O check placeholder
placeholder
не имеет значения, это /path/to/socket
то, что идентифицирует основное соединение, которым вы хотите управлять.
Теперь вы можете запросить переадресацию портов:
ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder
Команда сообщит вам порт. Он выйдет сразу, это означает, что вы смогли зафиксировать вывод. Ничего не потеряно. Повторите команду, и он снова сообщит вам тот же порт вместо переадресации второго порта на тот же пункт назначения. Итак, давайте сохраним вывод в переменную:
port="$(ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder)"
Вот и все, теперь вы можете использовать переменную.
Для полноты картины отмените переадресацию:
ssh -S /path/to/socket -O cancel -R 0:localhost:22 placeholder
хотя вам не нужно явно отменять перед завершением основного соединения. Вы завершаете это так:
ssh -S /path/to/socket -O exit placeholder
Не все приведенные выше команды необходимы в самом простом скрипте. Вам нужны эти:
ssh -fNMS /path/to/socket user@server
port="$(ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder)"
# anything you want, now you know the port
ssh -S /path/to/socket -O exit placeholder
возможно, с некоторой логикой для обработки connection refused
и т. д.