0

I try to make a dummy script for debugging. The script should pass the command and all params to syslog. But when I get a param which has quotes I only get a failure.

#!/bin/sh

set -x
param="$*"

logger -t $0 -p local3.debug "$*"
#logger -t $0 -p local3.debug "$param"
#logger -t $0 -p local3.debug "$(echo "$param")"
#logger -t $0 -p local3.debug "${param//\"/}"
#logger -t $0 -p local3.debug "${param[@]}"

I tryd some variants I found, but nothing works.

# d-iptables -L dkdsdds "ddd"
+ param='-L dkdsdds ddd'
++ echo '-L dkdsdds ddd'
+ logger -t /usr/sbin/d-iptables -p local3.debug '-L dkdsdds ddd'
logger: invalid option -- L

Usage:
 logger [options] [message]

Options:
 -d, --udp             use UDP (TCP is default)
 -i, --id              log the process ID too
 -f, --file <file>     log the contents of this file
 -h, --help            display this help text and exit
 -n, --server <name>   write to this remote syslog server
 -P, --port <number>   use this UDP port
 -p, --priority <prio> mark given message with this priority
 -s, --stderr          output message to standard error as well
 -t, --tag <tag>       mark every line with this tag
 -u, --socket <socket> write to this Unix socket
 -V, --version         output version information and exit
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Thomas
  • 1,193
  • 1
  • 7
  • 16
  • 4
    Sounds like [Bash FAQ 50](http://mywiki.wooledge.org/BashFAQ/050). Your immediate problem is that you want `"$@"` but I'm guessing it won't take you all the way where you think you want to be going. But just don't want to go there. – tripleee May 20 '16 at 15:47
  • I only want to esape the quotes inside the var, that I can pass them as message to logger – Thomas May 20 '16 at 15:57
  • If you are trying to forward arguments to some other command verbatim then just use `"$@"` when calling the other command as tripleee indicated. If that *doesn't* work for what you are trying to do (and I'm certain it will) then edit your question to indicate *why* you think it doesn't. – Etan Reisner May 20 '16 at 16:07
  • If you're going to post your own answer, post it as a new answer; don't edit it into the question -- that way that answer can be upvoted/downvoted/commented on/etc. separate from the question. – Charles Duffy May 20 '16 at 17:04
  • sorry, I dont wanted to whip the good hints, which helped me to find my way :) – Thomas May 20 '16 at 17:23

2 Answers2

2

I would suggest you change your script to #!/bin/bash and use

logger -t $0 -p local3.debug -- "$(printf "%q " "$@")"

You need the -- so logger doesn't think the -L is one of its options.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • its not bad, but in syslog I dont get the quotes -> /usr/sbin/d-iptables: -L dkdsdds ddd :( – Thomas May 20 '16 at 16:26
  • You cannot: your shell removes them before your script even starts – glenn jackman May 20 '16 at 16:35
  • really sure the is no way?! IFS, for loop, or something else? – Thomas May 20 '16 at 16:40
  • 1
    Yes, really sure. Assuming your shell is bash, there is a defined list of expansions that occurs before commands are launched. Quote removal is one of those expansions. Your script will never know how the user quoted the arguments. – glenn jackman May 20 '16 at 16:43
  • Check my answer. To preserve them? No way. To add them after they are removed (or missing)... yes. – SaintHax May 20 '16 at 16:46
  • found a way for reqoute: http://stackoverflow.com/a/24179878/1426827 -- this is better than nothing :) – Thomas May 20 '16 at 16:49
  • @Thomas, that `requote` function given there has some serious (ie. security-impacting, if anything evaluates the output) bugs. You're much better off relying on `printf %q` instead, as given in this answer -- perhaps the ksh93 implementation if you have that shell available, as its output is somewhat easier-to-read than the bash one. – Charles Duffy May 20 '16 at 16:56
  • I have seen you have added some comments to Chen Levy answer. It means, with your corrections, the function is more safe? Have you a complete snippet? – Thomas May 20 '16 at 17:15
  • No, the corrections I've offered thus far don't make Chen's answer more safe, only higher-performance. – Charles Duffy May 20 '16 at 17:23
  • was the function or better "usage" in my question edit more safe? – Thomas May 20 '16 at 17:24
  • The usage in your edit was `eval`-safe, inasmuch as the output from `requote` always went through `printf %q`, but it compromised on correctness to get there (double-escaping contents). – Charles Duffy May 20 '16 at 17:29
  • Probably, building a good equivalent to ksh's `printf %q` for bash needs to be its own question. (The ksh one does everything Chen's answer provided out-of-the-box while also being correct and safe in the corner cases, whereas while the bash `printf %q`'s output is syntactically correct for the parser, it's not very easy for humans to read in the simple cases, which is presumably why you were adding `requote` to it in addition). – Charles Duffy May 20 '16 at 17:29
  • @Thomas, ...to be clear, the output of glenn's answer should give you everything you need to distinguish between `d-iptables -L foo bar` and `d-iptables -L "foo bar"`, without needing `requote`; for the first case, it would run logger with `foo bar`, for the second, `foo\ bar` -- which is quite correct, as `d-iptables -L "foo bar"` and `d-iptables -L foo\ bar` are indistinguishable to the shell. It's just not as human-readable as some other formulations would be. – Charles Duffy May 20 '16 at 17:34
  • okay, now I can see that the answer also works without the requote. I have not checked with the same param input - I testet before with the requote function. Thanks to make it clear to me. – Thomas May 20 '16 at 17:46
0

First you have tagged this as bash, but you are using /bin/sh (which is either bourne or dash). Next your logger is reading the - as an argument. Just quote it better.

#!/bin/bash

set -x
param="\"$@\""     # quotes removed by the shell

logger -t $0 -p local3.debug "'$param'"  # expand, then strong quote
SaintHax
  • 1,875
  • 11
  • 16
  • Why in the world would you want to assign an array to a scalar variable? – Charles Duffy May 20 '16 at 16:50
  • Holy Perl lingo, Batman! B/c in this case, the array is a string. It is in fact how the OP was treating it, and I see no reason to make it an array. Why would you want to assign a string to an array? No need. – SaintHax May 20 '16 at 16:57
  • The OP *wants* to make a string from their array, yes, but `param="\"$@\""` isn't actually doing that in a useful way. I mean, if you had `set -- "first item" "second item"`, the desired output is presumably a single string that shows those quoted together, right? Something like `param="'first item' 'second item'"`? Your code doesn't accomplish that. – Charles Duffy May 20 '16 at 17:03
  • ...by contrast, `printf -v param '%q ' "$@"` would (in bash) assign something like `param='first\ item second\ item'`, making it clear which whitespace is syntactical and which whitespace is literal. (In ksh, it would do even better, following the `'first item' 'second item'` model). – Charles Duffy May 20 '16 at 17:07
  • ksh is not germane. And it doesn't matter if printf shows the literal/syntactical, b/c logger will eat them and it will be obscured in the final product. In addition, logger takes ONE argument-- a string as the message. So, you are coding on an assumption that there is more than one argument, when there can't be. ? `logger "this is" "messed up"` is not a valid behavior. – SaintHax May 20 '16 at 17:19
  • Sure, but `logger '"this is" "messed up"'` is both valid **and desirable**, inasmuch as the OP's question is about passing "all params" (which specifies **multiple** parameters) through in a way that honors "quotes" (plural, from the OP's question). – Charles Duffy May 20 '16 at 17:21
  • So yes, we're combining multiple arguments into one argument, but doing that in a way that disregards the original argument boundaries is throwing away information. – Charles Duffy May 20 '16 at 17:23
  • See also the OP's use of the `requote` function in the answer they (previously) edited into the question (check history); `requote` has no purpose if one **doesn't** intend to represent the distinction between literal and syntactic whitespace in multiple arguments. – Charles Duffy May 20 '16 at 17:31