Странное поведение grep/head при конвейеризации

Странное поведение grep/head при конвейеризации

Я помогаю сетевому администратору с помощью регулярного выражения Perl для автоматизации работы с некоторыми снимками из нашей SAN, и наши скрипты делают что-то вроде этого:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$1/')

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$2/')

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

tcp: [32] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1
tcp: [33] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

Желая извлечь из того, что было результатом icsiadm и grep, получить это:

iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

и

r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

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

head: cannot open '–n1' for reading: No such file or directory

Конечно, это, по-видимому, указывает на то, что стандартный поток ввода head пуст, поэтому выполняется поиск имени файла.

Но нет никаких причин, по которым он когда-либо будет пустовать.

Если мы сделаем что-то вроде этого:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

второй вызовет ошибку, и вторая переменная будет пустой.

Однако если мы поменяем их местами, то varsnap1 завершится ошибкой:

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

Это очень странно, и мы не можем понять, что происходит. Команда iscsiadm возвращает одно и то же при каждом запуске из командной строки и после grepping.

Что-то засорило трубопровод?

версия 5.97 на RedHat Enterprise Linux

решение1

Хотя ваш вопрос, возможно, содержит ошибку (длинное тире utf8 вместо обычного):

$ head –n1
head: cannot open ‘–n1’ for reading: No such file or directory
$ head -n1 # ctrl-d
$ 

Я предположу, что это просто особенность браузера, так как только один раз было похожее. headждет ввода, когда он ему нужен. Попробуйте заменить head -n1на один из этих:

sed -n 1p
awk 'NR==1 {print}' # yay, no potential dash problems

Хорошо, есть еще много способов сделать это, но вы также можете пропустить этот элемент конвейера и просто указать, grepчто нужно вернуть только первое совпадение, добавив -m 1параметр. Или исключить два элемента и указать, perlчто нужно работать только с первой совпавшей строкой.

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