LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-19-2012, 04:53 AM   #1
masuch
Member
 
Registered: Sep 2011
Location: /dev/null
Distribution: ubuntu 64bits
Posts: 135

Rep: Reputation: 1
Question run ps|grep command by script/command line ... ERROR: Unsupported option (BSD syntax)


Hi,

I run ps ax|grep something without any problem.
when I put it in script I have got ERROR:


ERROR: Unsupported option (BSD syntax)
********* simple selection ********* ********* selection by list *********
-A all processes -C by command name
-N negate selection -G by real group ID (supports names)
-a all w/ tty except session leaders -U by real user ID (supports names)
-d all except session leaders -g by session OR by effective group name
-e all processes -p by process ID
T all processes on this terminal -s processes in the sessions given
a all w/ tty, including other users -t by tty
g OBSOLETE -- DO NOT USE -u by effective user ID (supports names)
r only running processes U processes for specified users
x processes w/o controlling ttys t by tty
*********** output format ********** *********** long options ***********
-o,o user-defined -f full --Group --User --pid --cols --ppid
-j,j job control s signal --group --user --sid --rows --info
-O,O preloaded -o v virtual memory --cumulative --format --deselect
-l,l long u user-oriented --sort --tty --forest --version
-F extra full X registers --heading --no-heading --context
********* misc options *********
-V,V show version L list format codes f ASCII art forest
-m,m,-L,-T,H threads S children in sum -y change -l format
-M,Z security data c true command name -c scheduling class


....
If I remove grep command - it works.
If I put ps ax|grep --ignore-case something into script ...
this error appeared again - which is confusing because
grep should use "GNU long options" but NOT "BSD options".

run it in command line in terminal - there is no problem at all. Only in script problem appeared.

where is the problem ?
is it some bug of grep command ?

thank you,
kind regards,
Martin
 
Old 05-19-2012, 03:27 PM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by masuch View Post
when I put ps ax|grep something in script I have got ERROR
Because you did not say what kind of script (shell script? Perl? Python) or even what command you used to run ps ax|grep something in your script, it is very difficult to answer anything meaningful. We need the details!

However..

Pipe | is a shell construct. It looks like your command is not run using a shell, but directly, so that instead of ps ax being run with its output piped to grep something (which is all set up by the shell), you only run ps with parameters ax|grep and something.

A simple way to fix that is to explicitly use a shell to run the command. For example,
Code:
sh -c "ps ax | grep something "
 
Old 05-19-2012, 06:58 PM   #3
masuch
Member
 
Registered: Sep 2011
Location: /dev/null
Distribution: ubuntu 64bits
Posts: 135

Original Poster
Rep: Reputation: 1
OK, thank you for answer.

This problem did not appear long time before - just after I did some changes in one script of complex of shell /bin/bash scripts.
! BUT I did not change "ps ax|grep -i something" at all in that script !
Weird is that after reboot computer - this error disappeared and everything got into normal and works properly. So, technically I could marked this post as solved but I am very interested how to investigate more deeply - what actually happened and why ?
(I did not have to use "sh -c ..." construct")

You mentioned:
"
...
instead of ps ax being run with its output piped to grep something (which is all set up by the shell), you only run ps with parameters ax|grep and something.
...
"

How can I determinate the way how the shell is going to interpreted command "(parameters or piped in this particular case)" ?
... any help/hint/URLs/doc much appreciate.

thank you,
kind regards,
M.


P.S.:
---- I am using this almost on the beginning of that specific bash script:
CMDLN_ARGS="$@"
export CMDLN_ARGS
# Run this script as root if not already.
chk_root () {
if [ ! $( id -u ) -eq 0 ]; then
my_fake_constructor_function
echo "Please enter root's password."
exec su -c "("${0}" ${CMDLN_ARGS} 2>&1) | tee ${_log_file}"
RETVAL=${?}
echo "------ ERROR: something really bad happened !"
echo "------ return code=${RETVAL}"
exit ${RETVAL}
else
my_fake_constructor_function
fi
}
chk_root

hope it does not cause that mentioned problem (when I added this small part) but 'ps ax|grep --ignore-case "something"' works now.
???
 
Old 05-20-2012, 03:10 PM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by masuch View Post
So, technically I could marked this post as solved but I am very interested how to investigate more deeply - what actually happened and why ?
I'd need a lot more details -- the exact file, the exact commands, and the exact error messages -- to be confident, but based on the effects and the snippet, I'd say either the su default shell was temporarily changed (by setting the SHELL variable), or the shell options related to parameter expansions had changed.

I am quite confident the error was related to expansion: that instead of being parsed as a shell command line, it was parsed as a single command. In other words, the pipe character (|) was not interpreted by the shell at all. It does not matter at all which commands you had on either side. If the commands did not have any quote characters, then they could not have affected this at all; it would have happened to any command. If you did use quotes, then you might have accidentally quoted the pipe too; perhaps by having unbalanced quotes.

I wouldn't worry about it, though, unless it reoccurs.

The way you have constructed your script is very fragile. In particular,
Code:
CMDLN_ARGS="$@"
exec su -c "(\"${0}\" ${CMDLN_ARGS} 2>&1 )" | tee ${_log_file}"
is not safe; it causes the command line to be re-split if not run as root, with expansions done twice. In other words, it has very different behavior wrt. command line parameters when run as root, than when run as any other user. Dangerous.

In your case, if you could use sudo instead of su, you could use
Code:
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
    sudo -- "$0" "$@" 
    exit $?
fi

# You are now root, do the rest of the stuff...
If you have to use su, then you need to convert the parameters to a single string, which is quite cumbersome. I think this should work, though:
Code:
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
    argstring=""
    squote="'\"'\"'"
    for arg in "$0" "$@"; do
        argstring="$argstring'${arg//\'/$squote}' "
    done
    argstring="${argstring% }"
    exec su --shell /bin/bash -c "$argstring"
    exit $?
fi

# You are now root, do the rest of the stuff...
The above constructs a string containing each argument in single quotes into argstring. The only character that should need any escaping is the single quote itself. It cannot be escaped, but you can temporarily switch to double quotes; 'foo'"'"'bar' evaluates to foo'bar . The first argument is of course the path to this script ($0), which needs to be escaped just like the others.


EDIT: Bash built-in printf might actually be a much easier solution for this:
Code:
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
    exec su --shell /bin/bash -c "$(printf '%q ' "$0" "$@")"
    exit $?
fi

# You are now root, do the rest of the stuff...
To handle the logging in the rest of your command -- I'd personally try hard to avoid logging the sudo or su password conversation --, I would suggest continuing the script with
Code:
# You are now root, do the rest of the stuff...
(   # If logging, combine stderr to stdout.
    [ -n "$_log_file" ] && exec 2>&1

    #
    # Do the real work in this part!
    #

) | (
    [ -n "$_log_file" ] && exec tee "${_log_file}"
    exec cat
)
This way you can just unset or clear _log_file to empty string (before this part is executed, of course!), to disable logging. If logging is NOT used, then the script will keep stdout and stderr separate, which is sometimes quite useful.

The logic is as follows:
If we do not have a log file, then the standard error of the work part goes directly to standard error (NOT via the pipe), and standard output to standard output via the pipe and cat.
If we do have a log file, then standard error is merged to standard output in the subshell, so that its standard error is also redirected to the pipe. At the other end of the pipe, teewill duplicate everything to both the log file and to standard output.

Although we use a subshell for both the work and the logging, the execs in the latter replace the subshell with the actual command. Thus, there is only one "extra" subshell, the one doing the work.

Note that you do need to do all work where I added the command. Not only because only that part will be logged, but also because it is a subshell, and any changes it makes to variables or environment will not be visible in the parent shell. Other than that, there should be no quirks to worry about.

Quote:
Originally Posted by masuch View Post
How can I determinate the way how the shell is going to interpreted command
The Shell Expansions section in the Bash Reference Manual describes it in detail. Also see the Quoting chapter for details on proper quoting.

Any questions?

I hope you find this useful,

Last edited by Nominal Animal; 05-20-2012 at 03:23 PM.
 
Old 05-23-2012, 05:13 AM   #5
masuch
Member
 
Registered: Sep 2011
Location: /dev/null
Distribution: ubuntu 64bits
Posts: 135

Original Poster
Rep: Reputation: 1
Hi,

Thanks a lot for this induction to bash scripting - I really appeciate it.
I am slowly implementing your suggestions to many scripts - using combinations of your suggestions.
(I have noticed as well that just in only one case - I had to put command 'ps aux|grep -i "/usr/bin/psensor-server &"' at the begging of the line - if I had some spaces at the begining of the line - it went wrong - do not why.


--- in development is following example - no ammended version yet. Beggining of the shell scripts:
#!/bin/bash
my_fake_constructor_function() {
# get directory of this script:
_SCRIPT_PATH="${BASH_SOURCE[0]}";
if([ -h "${_SCRIPT_PATH}" ]) then
while([ -h "${_SCRIPT_PATH}" ]) do _SCRIPT_PATH=`readlink "${_SCRIPT_PATH}"`; done
fi
_SCRIPT_PATH=`readlink -f $(dirname "${_SCRIPT_PATH}")`

# get timestamp now:
_datetimenow=`date +%Y%m%d--%H-%M-%S`

# log file
#mkdir -p "${_SCRIPT_PATH}/_logs"
_log_file="${_SCRIPT_PATH}/`hostname`--${0##*/}--${_datetimenow}.log"
}

CMDLN_ARGS="$@"
export CMDLN_ARGS
chk_root () {
if [ ! $( id -u ) -eq 0 ]; then
my_fake_constructor_function
echo "Please enter root's password."
exec su -c "("${0}" ${CMDLN_ARGS} 2>&1) | tee ${_log_file}"
RETVAL=${?}
echo "------ ERROR: something really bad happened !"
echo "------ return code=${RETVAL}"
exit ${RETVAL}
else
my_fake_constructor_function
fi
}
chk_root
sudo echo ""
...



(--- basicaly it runs script as root with output as on the screen as to the log file (which is my intention).)



--- one part of the script - one function (ps command)
(it is testing if application runs (by pidof and ps) - if not - it is going to start that application
(but I still have some problems to solve - like DBUS_SESSION_BUS_ADDRESS - as you can see :-)



startrestartaplls() {
y=`expr $# / 2`
for (( x=0; x<y; x++ )); do
LIST1[x]="$1"
LIST2[x]="$2"
shift
shift
done
for (( A=0; A<$y; A++ )); do # ${#LIST1[*]}/2
echo ""
echo "---------------------------------------------------------------------- '${LIST1[$A]}' '${LIST2[$A]}'"
_process="${LIST2[$A]}"
_pidof=`pidof ${_process}`
RETVAL=$?
if [ "${RETVAL}" == "0" ]; then # 0 At least one program was found with the requested name.
if [ -z "${_pidof}" ]; then
echo " --- process is NOT running: ${_process}"
ps aux|grep -i ${_process}
else
echo " --- process is running: ${_process} with PID=${_pidof}"
fi
elif [ "${RETVAL}" == "1" ]; then # 1 No program was found with the requested name.
echo " --- process does NOT EXIST: ${_process}"
ps aux|grep -i ${_process}
#su --login root --shell /bin/bash --command "${LIST1[$A]}"
echo "DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS
su --login root --preserve-environment --command "${LIST1[$A]}"
RETVAL=$?
echo "retval=$RETVAL"
case "$RETVAL" in
"0")
echo "success (--help only)" >/dev/null
;;
"1")
echo "ERROR: System or authentication failure."
;;
"126")
echo "ERROR: The requested command was not found."
;;
"127")
echo "ERROR: The requested command could not be executed."
;;
*)
echo "ERROR: Some weird error happened."
;;
esac
else
echo " --- pidof returned ERROR=${RETVAL}"
fi
done
}

--- one of the input is like following:
_appl_2x_array=("/usr/bin/pglcmd restart" "pgld" "/opt/xplico/script/sqlite_demo.sh &" "xplico" "/usr/local/sbin/dnscrypt-proxy --daemonize &" "dnscrypt-proxy" "/usr/bin/psensor-server &" "psensor-server" "vidalia &" "vidalia")

--- At this moment it is under development - something works something not
(example: 'vidalia &' does not work - if executed from the script but works from terminal command line) :-)

--- I cannot put here even one whole script - because it is long and under re/development.
--- In some cases I do not have to use su (can use sudo) - in some scripts I have to :-)


thank you again - your suggestions are going to be implemented in many scripts :-)
 
  


Reply

Tags
bsd, command, error, grep, script


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] Repeatedly getting command substitution: line 3: syntax error near unexpected token dontob Linux - General 8 08-31-2010 09:26 AM
run php script from command line blizunt7 Programming 11 11-06-2008 12:59 PM
Command syntax question for grep kaplan71 Linux - Software 4 07-16-2008 03:13 PM
Help me in Grep Command + cd command in single line JeiPrakash Linux - Newbie 3 05-27-2008 05:16 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:03 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