run gdb batch command with `` incorrect - shell

>cmd="/usr/bin/gdb -q --batch -ex 'thread apply all bt full' /proc/8969/exe /tmp/core.xxx"
>ret=`$cmd`
Excess command line arguments ignored. (bt ...)
apply: No such file or directory.
/etc/all: No such file or directory.
Undefined command: "". Try "help".
>echo $ret
>
But -ex 'thread apply all bt full' change to -ex 'bt', the result is correct.
I don't know why,and how to fix it.
type /usr/bin/gdb -q --batch -ex 'thread apply all bt full' /proc/8969/exe /tmp/core.xxx" in command line and execute success

cmd="/usr/bin/gdb -q --batch -ex 'thread apply all bt full' /proc/8969/exe /tmp/core.xxx
ret=`$cmd`
After parameter expansion of $cmd, the shell will do field splitting, which splits using the delimiters in $IFS (typically white space). This results in the following fields:
/usr/bin/gdb
-q
--batch
-ex
'thread
apply
all
bt
full'
/proc/8969/exe
/tmp/core.xxx
This tells GDB to execute a command named 'thread, and to debug an executable named apply and core file all.
One way to get the results you want is to run
ret=`eval "$cmd"`
echo "$ret" # use quotes here to preserve newlines
If you use bash or other modern shells that support arrays, this might be better:
gdbargs=(-q --batch -ex 'thread apply all bt full' /proc/8969/exe /tmp/core.xxx)
ret=`/usr/bin/gdb "${gdbargs[#]"}`
echo "$ret"

Related

How to break down the following command, so it can be used in a Bash script?

I am trying to write a Bash script for a custom rofi menu. This menu would have different choices for different custom commands. Currently, I am trying to see if I can write a Bash script to execute a single command. The command is:
exec /home/user/.config/i3/myscript.sh 'todolist' 'xfce4-terminal --command "emacs -nw -Q -l ~/.emacs.d/script.el ~/Dropbox/mytodo.org" '
This is a very long command so I break it down like this:
COMMAND=("/home/user/.config/i3/myscript.sh")
EMACS=(" 'todolist' 'xfce4-terminal --command "emacs -nw -Q -l ~/.emacs.d/script.el ~/Dropbox/mytodo.org"' ")
I tried to echo out: echo $COMMAND $EMACS. The result I got is:
/home/user/.config/i3/script.sh 'todolist' 'xfce4-terminal --command emacs
So, everything from the -nw -Q -l forward are ignored. As a result, it is an incomplete command. How can I fix the second variable EMACS?
Parentheses in a variable assignment in Bash are used to create arrays. The array items are separated by space. Here's an example:
arr=(0 1 2)
echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}
So in your case:
EMACS=(" 'todolist' 'xfce4-terminal --command "emacs -nw -Q -l ~/.emacs.d/script.el ~/Dropbox/mytodo.org"' ")
The expression ${EMACS[0]} will contain 'todolist' 'xfce4-terminal --command emacs, the expression ${EMACS[1]} will have the value -nw, and so on.
Also, notice that " 'todolist' etc. "emacs is just the juxtaposition of the strings " 'todolist' etc. " and emacs, so the result will be the concatenation of all characters without the quotes.
My suggestion is that you use variables for the files and keep the rest in plain bash. Use a backslash to break the command into multiple lines if you feel one line is too long:
MY_SCRIPT="${HOME}/.config/i3/myscript.sh"
EMACS_SCRIPT="${HOME}/.emacs.d/script.el"
DROPBOX_FILE="${HOME}/mytodo.org"
exec "$MY_SCRIPT" todolist xfce4-terminal \
--command "emacs -nw -Q -l ${EMACS_SCRIPT} ${DROPBOX_FILE}"

What does `+option` mean in a bash command?

I have never seen some special bash format before.
special bash command :foo -a -c +b
foo -a -c +b
foo is a bash command ,a and c are foo's options.
For the above command ,what does +b mean here?
To disable an option within a script.
foo command has the b option ,or say,there is a b behavior in foo command,
foo -a -c +b is to invoke ac behavior and disable b behavior.
Why not just run with :
foo -a -c
According to the Advanced Bash-Scripting Guide, for bash options:
-option enables an option that defaults to disabled
+option disables an option that defaults to enabled
So it would make sense that other programs would follow the same method of enabling and disabling options.
A bash example given is:
#!/bin/bash
set -o verbose
# Command echoing on.
command
...
command
set +o verbose
# Command echoing off.
command
# Not echoed.
set -v
# Command echoing on.
command
...
command
set +v
# Command echoing off.
command
exit 0

Bash script for GDB

I have an script that I used for debugging with GDB where I set breakpoints before execution:
#!/bin/bash
bps=( 'fer_couple.c:50' )
# BREAKPOINTS
for i in ${bps[#]}
do
exopt="$exopt -ex 'break $i' "
done
echo $exopt
gdbcomm="gdb $exopt --args ../../fermi fuel_1.fer -c couple.dat"
echo $gdbcomm
mpirun -np 1 xterm -e $gdbcomm : -np 1 xterm -e gdb control
the problem is that when I run this I have the error in GDB:
Undefined command: "". Try "help"
But as you see in the last echo if you type the command manually:
gdb -ex 'break fer_couple.c:50' --args ../../fermi fuel_1.fer -c couple.dat
I don't have that problem. Probably I am doing something wrong with the bash variables. Thank you.
A couple of things standout, mainly the quoting (lackof) and how gdb is executed.
for i in "${bps[#]}"
do
exopt="$exopt -ex 'break $i' "
done
Since you are using an array double-quote it to avoid re-splitting elements. With the gdb command itself it's probably better to use a sub-shell, for example:
gdbcomm=$(gdb "$exopt" --args ../../fermi fuel_1.fer -c couple.dat)
Also double-quote the $exopt variable, since that is where the command currently breaks. You can check the syntax of your script through http://shellcheck.net for similar errors/warnings.
You can debug the Bash script also.Use this option
set -x # activate debugging from here
w
set +x # stop debugging from here
Add this in the 2nd line
#!/bin/bash
set -x # activate debugging from here
bps=( 'fer_couple.c:50' )
# BREAKPOINTS
for i in ${bps[#]}
do
exopt="$exopt -ex 'break $i' "
done
echo $exopt
gdbcomm="gdb $exopt --args ../../fermi fuel_1.fer -c couple.dat"
echo $gdbcomm
mpirun -np 1 xterm -e $gdbcomm : -np 1 xterm -e gdb control
set +x # stop debugging from here
I was able to reproduce problem that you get. For solving it at the end of script instead of
mpirun -np 1 xterm -e $gdbcomm : -np 1 xterm -e gdb control
use
tail_comm=" : -np 1 gdb control"
xterm -e "$gdbcomm $tail_comm"
I am not sure, but it seems that the problem was that the variable gdbcomm is string with spaces.
Finally I have added " to $gdbcomm and It worked
#!/bin/bash
bps=( 'fer_couple.c:50' )
# BREAKPOINTS
for i in ${bps[#]}
do
exopt="$exopt -ex 'break $i' "
done
gdbcomm="gdb $exopt --args ../../fermi fuel_1.fer -c couple.dat"
mpirun -np 1 xterm -e "$gdbcomm" : -np 1 xterm -e gdb control
Other option that it works and likes me more is to use eval(http://www.unix.com/man-page/posix/1posix/eval/):
eval mpirun -np 1 xterm -e gdb $exopt --args ../../fermi fuel_1.fer -c couple.dat : -np 1 xterm -e gdb control

Bash: Execute command WITH ARGUMENTS in new terminal [duplicate]

This question already has answers here:
how do i start commands in new terminals in BASH script
(2 answers)
Closed 20 days ago.
So i want to open a new terminal in bash and execute a command with arguments.
As long as I only take something like ls as command it works fine, but when I take something like route -n , so a command with arguments, it doesnt work.
The code:
gnome-terminal --window-with-profile=Bash -e whoami #WORKS
gnome-terminal --window-with-profile=Bash -e route -n #DOESNT WORK
I already tried putting "" around the command and all that but it still doesnt work
You can start a new terminal with a command using the following:
gnome-terminal --window-with-profile=Bash -- \
bash -c "<command>"
To continue the terminal with the normal bash profile, add exec bash:
gnome-terminal --window-with-profile=Bash -- \
bash -c "<command>; exec bash"
Here's how to create a Here document and pass it as the command:
cmd="$(printf '%s\n' 'wc -w <<-EOF
First line of Here document.
Second line.
The output of this command will be '15'.
EOF' 'exec bash')"
xterm -e bash -c "${cmd}"
To open a new terminal and run an initial command with a script, add the following in a script:
nohup xterm -e bash -c "$(printf '%s\nexec bash' "$*")" &>/dev/null &
When $* is quoted, it expands the arguments to a single word, with each separated by the first character of IFS. nohup and &>/dev/null & are used only to allow the terminal to run in the background.
Try this:
gnome-terminal --window-with-profile=Bash -e 'bash -c "route -n; read"'
The final read prevents the window from closing after execution of the previous commands. It will close when you press a key.
If you want to experience headaches, you can try with more quote nesting:
gnome-terminal --window-with-profile=Bash \
-e 'bash -c "route -n; read -p '"'Press a key...'"'"'
(In the following examples there is no final read. Let’s suppose we fixed that in the profile.)
If you want to print an empty line and enjoy multi-level escaping too:
gnome-terminal --window-with-profile=Bash \
-e 'bash -c "printf \\\\n; route -n"'
The same, with another quoting style:
gnome-terminal --window-with-profile=Bash \
-e 'bash -c '\''printf "\n"; route -n'\'
Variables are expanded in double quotes, not single quotes, so if you want them expanded you need to ensure that the outermost quotes are double:
command='printf "\n"; route -n'
gnome-terminal --window-with-profile=Bash \
-e "bash -c '$command'"
Quoting can become really complex. When you need something more advanced that a simple couple of commands, it is advisable to write an independent shell script with all the readable, parametrized code you need, save it somewhere, say /home/user/bin/mycommand, and then invoke it simply as
gnome-terminal --window-with-profile=Bash -e /home/user/bin/mycommand

cygwin 1.7.15 handling of "set -e" in shell scripts (error in sub-shell causes parent to exit)

I am using this:
$ uname -a
CYGWIN_NT-6.1 bassoon 1.7.15(0.260/5/3) 2012-05-09 10:25 i686 Cygwin
$ bash --version
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)
$ cat myexpr.sh
#!/bin/sh
echo "In myexpr, Before expr"
ac_optarg=`expr x--with-gnu-as : 'x[^=]*=\(.*\)'`
echo "ac_optarg=$ac_optarg"
echo "In myexpr, After expr"
$ cat myexpr2.sh
#!/bin/sh
set -e
echo "In myexpr, Before expr"
ac_optarg=`expr x--with-gnu-as : 'x[^=]*=\(.*\)'`
echo "ac_optarg=$ac_optarg"
echo "In myexpr, After expr"
The only difference between the two scripts is that myexpr2.sh uses "set -e"
$ echo $$
2880
$ ./myexpr.sh
In myexpr, Before expr
ac_optarg=
In myexpr, After expr
$ ./myexpr2.sh
In myexpr, Before expr
Expected behavior, so far.
If I do this in the parent shell (PID 2880, above):
$ set -e
$ ./myexpr.sh
The parent shell exits! That is pID 2880 above where I did the "set -e"
This is not the behavior on Linux or cygwin 1.5.12. Is this a bug in cygwin or BASH on cygwin?
This is not a bug, it's a feature of the Bash environment. This happens when you don't have the Bash shell environment variable execfail set, and/or the Shell environment variable errexit.
execfail - (is a BASHOPTS)
If set, a non-interactive shell will not exit if it cannot execute
the file specified as an argument to the exec builtin command.
An interactive shell does not exit if exec fails.
errexit - (is a SHELLOPTS)
Exit immediately if a pipeline (see Pipelines), which may consist of a
single simple command (see Simple Commands), a subshell command enclosed
in parentheses (see Command Grouping), or one of the commands executed as
part of a command list enclosed by braces (see Command Grouping) returns a
non-zero status. The shell does not exit if the command that fails is part
of the command list immediately following a while or until keyword, part
of the test in an if statement, part of any command executed in a && or ||
list except the command following the final && or ||, any command in a
pipeline but the last, or if the command’s return status is being inverted
with !. A trap on ERR, if set, is executed before the shell exits.
This option applies to the shell environment and each subshell environment
separately (see Command Execution Environment), and may cause subshells to
exit before executing all the commands in the subshell.
Different Linux versions have different defaults for these.
You can check which are enabled with:
echo "SHELLOPTS=$SHELLOPTS"
echo "BASHOPTS=$BASHOPTS"
and you can see all of them using:
set -o && echo -e "\n" && shopt -p
So, you need to enable yours with:
shopt -s execfail
If that doesn't work, you may also have to unset (off) the errexit of $SHELLOPTS with:
set -o errexit
For further info, see: The GNU Bash Manual!
PS. "set" is using reverse logic so if you wanna use the 'e' flag you have to use a "+": set +e

Resources