LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 05-19-2015, 01:58 AM   #1
Weapon S
Member
 
Registered: May 2011
Location: Netherlands
Distribution: Debian, Archlinux
Posts: 262
Blog Entries: 2

Rep: Reputation: 49
Executing command from file (with tail) probably misquotes?


When working with a virtual terminal, I find it often easier to edit a file to execute than to construct a regular-expression etc. to inject the right UUID etc. into the command. I have run into an error while doing this. I suspect it is stems from quote mishandling, or improper escape sequences. (I ran directly from the command line earlier, forgot a quotation mark, and it gave a similar bad result.)
The program in question was efibootmgr. I had a file vaguely similar to this one, named efiboot.Hz:
Code:
efibootmgr -c -g -L "Debian (EFI stub)" -l '\EFI\debian\vmlinuz' -u 'root=UUID=$UUID ro quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\debian\\initrd.img'
efibootmgr -c -d /dev/sdb -L "Debian Linux" -l '\EFI\debian\vmlinuz' -u 'root=UUID=1234-ffff-789 ro quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\debian\\initrd.img'
Then I executed:
Code:
`tail -n 1 efiboot.Hz`
efibootmgr -v revealed the previous command produced a garbled name and boot options, and most importantly it didn't boot. Manually writing the last line on the terminal did produce the desired effect. I thought I checked the output from tail before putting the back-ticks.
What did I do wrong?
 
Old 05-19-2015, 08:08 AM   #2
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Wrong quote:
Code:
'root=UUID=$UUID ro quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\debian\\initrd.img'
The apostrophe disables substitution within the string. Use
Code:
"root=UUID=$UUID ro quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\debian\\initrd.img"
 
Old 05-19-2015, 11:45 AM   #3
Weapon S
Member
 
Registered: May 2011
Location: Netherlands
Distribution: Debian, Archlinux
Posts: 262

Original Poster
Blog Entries: 2

Rep: Reputation: 49
The single quote actually worked, when typed directly onto the command line. What happens, when I use `tail` to run it?
 
Old 05-19-2015, 03:31 PM   #4
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Nothing changes.

You have to pipe the output to tail - if the log is in a file then you can use tail to skip forward and backward in the file - but with a pipe you can't.
 
Old 05-19-2015, 04:09 PM   #5
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
He's not piping the command to tail, the command is in a file and he's using tail to execute it:
Code:
`tail -n 1 efiboot.Hz`
OP - please stick an "echo" in front of the command in your file, and then copy and paste the results of
Code:
tail -n 1 efiboot.Hz
`tail -n 1 efiboot.Hz`
 
Old 05-19-2015, 04:17 PM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
I think this might be one of those rare cases where using eval is the correct solution.

Quote:
Originally Posted by suicidaleggroll View Post
OP - please stick an "echo" in front of the command in your file, and then copy and paste the results of
Code:
tail -n 1 efiboot.Hz
`tail -n 1 efiboot.Hz`
Using echo won't always show word splitting correctly, I suggest instead compare outputs of

Code:
printf '[%s]\n' efibootmgr -c -d /dev/sdb -L "Debian Linux" -l '\EFI\debian\vmlinuz' -u 'root=UUID=1234-ffff-789 ro quiet rootfstype=ext4 add_efi_memmap initrd=\\EFI\\debian\\initrd.img'
printf '[%s]\n' `tail -n 1 efiboot.Hz`
 
1 members found this post helpful.
Old 05-23-2015, 03:24 AM   #7
Weapon S
Member
 
Registered: May 2011
Location: Netherlands
Distribution: Debian, Archlinux
Posts: 262

Original Poster
Blog Entries: 2

Rep: Reputation: 49
You seem to be on the right track, ntubski.
Line from file to be executed:
Code:
efibootmgr -c -d /dev/sdb -L "Debian Linux" -l '\EFI\debian\vmlinuz' -u 'root=UUID=3c049958-12f1-4323-bba4-b80ee37dcdc9 ro quiet rootfstype=ext4 add_efi_memmap initrd=\EFI\debian\initrd.img' -v
Expected result (output of efibootmgr -v)
Code:
Boot0001* Debian Linux	HD(1,800,100000,02087932-b340-4c33-9193-81dd0a1cf2c2)File(\EFI\debian\vmlinuz)r.o.o.t.=.U.U.I.D.=.3.c.0.4.9.9.5.8.-.1.2.f.1.-.4.3.2.3.-.b.b.a.4.-.b.8.0.e.e.3.7.d.c.d.c.9. .r.o. .q.u.i.e.t. .r.o.o.t.f.s.t.y.p.e.=.e.x.t.4. .a.d.d._.e.f.i._.m.e.m.m.a.p. .i.n.i.t.r.d.=.\.E.F.I.\.d.e.b.i.a.n.\.i.n.i.t.r.d...i.m.g.
Result from running with tail:
Code:
Boot0003* "Debian	HD(1,800,100000,02087932-b340-4c33-9193-81dd0a1cf2c2)File('\EFI\debian\vmlinuz')L.i.n.u.x.".'.r.o.o.t.=.U.U.I.D.=.3.c.0.4.9.9.5.8.-.1.2.f.1.-.4.3.2.3.-.b.b.a.4.-.b.8.0.e.e.3.7.d.c.d.c.9.r.o.q.u.i.e.t.r.o.o.t.f.s.t.y.p.e.=.e.x.t.4.a.d.d._.e.f.i._.m.e.m.m.a.p.i.n.i.t.r.d.=.\.E.F.I.\.d.e.b.i.a.n.\.i.n.i.t.r.d...i.m.g.'.
Command split by printf:
Code:
[efibootmgr]
[-c]
[-d]
[/dev/sdb]
[-L]
["Debian]
[Linux"]
[-l]
['\EFI\debian\vmlinuz']
[-u]
['root=UUID=3c049958-12f1-4323-bba4-b80ee37dcdc9]
[ro]
[quiet]
[rootfstype=ext4]
[add_efi_memmap]
[initrd=\EFI\debian\initrd.img']
[-v]
Result from typing in directly:
Code:
Boot0005* Debian Linux	HD(1,800,100000,02087932-b340-4c33-9193-81dd0a1cf2c2)File(\EFI\debian\vmlinuz)r.o.o.t.=.U.U.I.D.=.3.c.0.4.9.9.5.8.-.1.2.f.1.-.4.3.2.3.-.b.b.a.4.-.b.8.0.e.e.3.7.d.c.d.c.9. .r.o. .q.u.i.e.t. .r.o.o.t.f.s.t.y.p.e.=.e.x.t.4. .a.d.d._.e.f.i._.m.e.m.m.a.p. .i.n.i.t.r.d.=.\.E.F.I.\.d.e.b.i.a.n.\.i.n.i.t.r.d...i.m.g.
Command split by printf:
Code:
[efibootmgr]
[-c]
[-d]
[/dev/sdb]
[-L]
[Debian Linux]
[-l]
[\EFI\debian\vmlinuz]
[-u]
[root=UUID=3c049958-12f1-4323-bba4-b80ee37dcdc9 ro quiet rootfstype=ext4 add_efi_memmap initrd=\EFI\debian\initrd.img]
[-v]
If I understand correctly the shell normally evaluates the quote characters and splits up the arguments to the program accordingly, but when using backticks it immediately splits up the arguments. This page seems to suggest it is a quirk of the backticks. (But I've never run into problems otherwise, maybe because some programs check for interrupted arguments manually.)
 
Old 05-23-2015, 08:21 AM   #8
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by Weapon S View Post
If I understand correctly the shell normally evaluates the quote characters and splits up the arguments to the program accordingly, but when using backticks it immediately splits up the arguments.
It's a bit more complicated than that: token splitting happens first, then expansion, then word splitting on expansions, then quote removal on non-expansions. More details in the bash manual, specifically Shell-Operation and Shell-Expansions.

Quote:
Command split by printf:
The split is performed by the shell, not printf. This is significant because this splitting shows what any other command would see.

So the correct solution would be
Code:
eval "`tail -n 1 efiboot.Hz`"
The quotes around the backticks are important to avoid word-splitting twice. It doesn't matter for this particular command, but it's necessary if you want e.g. consecutive spaces in a single argument.
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Executing shell command from JSP file with command line arg from URL orcusomega Programming 2 01-13-2012 03:38 PM
Executing a command on file change ivanatora Linux - General 5 01-30-2009 01:01 PM
tail command help munna_dude Programming 4 10-08-2007 02:30 AM
Executing a command on every file in a directory asciimonster Linux - Newbie 2 06-14-2004 03:46 AM
PostgreSQL: executing a .SQL file from command line? J_Szucs Linux - Software 0 09-24-2003 11:49 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 07:33 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration