Bash – Peculiar piping grep/head behavior

bashgrepheadscripting

I'm helping the netadmin here with a perl regex to automate operating on some snapshots from our SAN and our scripts does stuff like this:

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/')

There are two pieces in the signature of the snapshot, one nested in the other and we're using the capturing groups to capture the name and a piece of the name for different subsequent commands which need to be performed. I know it's running the same command over and over, and the regex can be cleaned up later, but basically they are using perl to output one parens and and the other.

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

Wanting to capture out of that which was the result of the icsiadm and grep to get this:

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

and

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

The problem we're having is that sometimes the piping to head to get the first line is failing with:

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

Of course, this appears to indicate that the stdin to head is empty so it's looking for a file name.

But there's no reason for it to ever be empty.

If we do things like this:

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

the second one will fail and the second variable will be empty.

Yet if we reverse them, then varsnap1 will fail:

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

It's very peculiar and we can't figure out what's going on. The iscsiadm command is returning the same thing each run when we run it from the command-line, and after grepping.

Is there something messing up the piping?

head version 5.97 on RedHat Enterprise Linux

Best Answer

While your question maybe contains an error (long utf8 dash instead of the normal one):

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

I will supposed that was just a browser thing, since only one occurence was like that. head waits for input when it needs it anyway. Try replacing head -n1 with one of these:

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

Ok, there are plenty more ways of doing it, but you could also skip that pipe element and just tell grep to return only the first match by adding the -m 1 parameter. Or eliminating two elements and telling perl to operate on the first matching line only.

Related Question