BASH_VERSINFO differs from what bash --version shows - bash

I tried copying from /usr/local/Cellar/bash/4.4.19/bin/bash to /usr/local/bin/bash because which bash shows /usr/local/bin/bash.
~/cat /etc/shells
/usr/local/Cellar/bash/4.4.19/bin/bash
~/bash --version
GNU bash, version 4.4.19(1)-release (x86_64-apple-darwin17.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
echo $BASH_VERSINFO
3
How do I fix this?

bash --version shows the version that would be run if a new shell were started from the PATH.
Thus, this version correlates with the install location from which bash (if not modified by aliases/functions/etc), or type bash (more accurately), or with the shell used to run a script with a #!/usr/bin/env bash shebang.
$BASH_VERSINFO and $BASH_VERSION show the version that's running right now.
Thus, if you're in a script with a #!/bin/bash shebang, or an interactive shell script for a user whose password database specifies /bin/bash as their shell, /usr/local/bin/bash (or any other location) being earlier in the PATH is irrelevant for purposes of the current, not-started-from-the-PATH shell instance.
To start the shell from the PATH in a script, change your shebang to #!/usr/bin/env bash. To start a specified shell from an interactive session, use chsh to update your account's settings.

Related

Makefile: writing filtering outputs to separate files [duplicate]

I found a difference of behaviour between GNU Make 4.1 and 3.81 and wonder whether my code is not POSIX compliant which 4 is enforcing more strictly, or whether something else is going on.
I distilled the failure case to this Makefile
.POSIX:
all: test-b
test-a:
cat a.txt b.txt c.txt >results.txt
test-b:
cat {a,b,c}.txt >results.txt
Assuming those files have been created with cat {a,b,c}.txt, target test-a always works, yet test-b works on Make 3.81 but fails on 4.1.
The output for 3.81:
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
$ make
cat {a,b,c}.txt >results.txt
$ echo $?
0
The output for 4.1:
$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ make
cat {a,b,c}.txt >results.txt
cat: {a,b,c}.txt: No such file or directory
Makefile:9: recipe for target 'test-b' failed
make: *** [test-b] Error 1
$ echo $?
2
It's possible the cat command is actually failing in 3.81 and it just isn't pointing it out, as later versions of GNU Make mention passing the -e flag to the shell when invoking target commands to make it more POSIX compliant, but I can't see how that command could be failing.
I assume the wildcards are handled solely by the shell, so I can't see how invoking the shell via a make target command should be any different.
Which is these behaviours are correct? If wildcards like that don't work in Makefiles, which other wildcards can I assume to work?
test-b still fails in 4.1 even if .POSIX: is removed from the file.
Recipes are sent to the shell. They are not interpreted by make. So your question is really, are curly-brace expansions supported by the shell?
That depends on which shell make uses. They are not supported by POSIX standard sh. They are supported by bash (and many other shells).
Make always invokes /bin/sh, regardless of what shell you personally use, unless you specifically set the make SHELL variable to something else. On some systems, /bin/sh is a symlink to /bin/bash so they are the same thing (bash runs in a "POSIX emulation" mode when invoked as /bin/sh but most bash features are still available). Other systems use different shells, such as dash, as /bin/sh which do not have extra bash features.
So, you can either (a) not have a portable makefile and assume /bin/sh is the same as /bin/bash, (b) set SHELL := /bin/bash in your makefile to force it to use bash always (but fail on systems that don't have bash installed), or (c) write your makefile recipes to use only POSIX sh features so it works regardless of which shell is used for /bin/sh.

cygwin bash tab completion for arguments fork failure

I have an odd problem with tab completion under cygwin's bash on my Win 7 installation. I get fork failures ('permission denied') under very specific circumstances..
Tab completion works fine for all commands.
Tab completion works fine for arguments of builtins and any cygwin-supplied program in /usr/bin, /usr/sbin, etc. (including .exe files as well as shell scripts)
Tab completion works fine for commands in my personal ~/bin directory.
However, whenever I attempt tab completion for an argument to one of my own shell scripts, I get a fork/permission denied error.
I've compared file permissions and ownerships of my shell scripts to those of cygwin-supplied shell scripts, and they are equivalent.
I've created a directory outside of the /cygwin/C hierarchy (named it /mybin) and copied my scripts into that directory. Then invoked the scripts directly (e.g., /mybin/gv n[TAB]) and the failure still occurs.
I've made sure the scripts have mode 775 and owned by me. I've made sure the directory in which the scripts exists is mode 775 and is also owned by me.
I haven't created anything in /usr/share/bash-completion (afaik, I shouldn't have to for argument-based filename completion). But I've not had issues with cygwin scripts without entries in /usr/share/bash-completion (e.g., /bin/zegrep is a shell script but has nothing under /usr/share/bash-completion)
I'm stumped at this point, but would like to resolve it since tab completion is such a vital feature.
Here's an example...
% gv n[TAB] 0 [main] bash 9308 fork: child -1 -CreateProcessW
failed for 'C:\Users\binaryb\cygwin\bin\bash.exe', errno 13 bash:
fork: Permission denied
.. in this example I was attempting to complete a filename (in current directory) by typing 'n[TAB]'. There is only one file starting with 'n' in my current directory.
I am running this under Win 7 (64 bit), with the following cygwin bash.exe version...
% uname -a
CYGWIN_NT-6.1 binaryb 2.10.0(0.325/5/3) 2018-02-02 15:16 x86_64 Cygwin
% bash --version
GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
I think I found the problem, but I'm not 100% sure. It seems to occur for scripts whose filenames are only 1 or 2 characters long. If I rename my script to, say, gvx, the problem goes away.
% gv n[TAB] 0 [main] bash 4556 fork: child -1 - CreateProcessW
failed for 'C:\Users\binaryb\cygwin\bin\bash.exe',
errno 13 bash: fork: Permission denied
% mv ~/bin/gv ~/bin/gvx
% gvx n[TAB]
% gvx newfile.txt

bash --version. Where this info are stored?

In which file are stored the info about the command
bash --version
?
I've tried in some directories like /bin or /var, /etc, but without results...
I need both for Linux and MAC OS x. Thanks!
Do you have any reason to believe that it is not hard-coded in the bash-executable itself?
To find out which bash is used, run
which bash
For me, it gives /bin/bash. Now, to see whether the executable has any string-like byte sequences in it that contain the substring "version", run
strings /bin/bash | grep version
On this machine, it gives:
shell_version_string
build_version
sccs_version
rl_library_version
rl_do_lowercase_version
show_shell_version
rl_readline_version
dist_version
GNU bash, version %s-(%s)
GNU bash, version %s (%s)
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
#(#)Bash version 4.3.48(1) release GNU
display-shell-version
-l do not print tilde-prefixed versions of directories relative
HOSTTYPE The type of CPU this version of Bash is running under.
OSTYPE The version of Unix this version of Bash is running on.
version, type `enable -n test'.
do-lowercase-version
.gnu.version
.gnu.version_r
Thus, "Bash version 4.3.48" is hard-coded in the executable as an ordinary string.
strings $(which bash) | grep "Bash version"
Output (e.g.):
#(#)Bash version 4.3.48(1) release GNU

Shell builtin - bind

Edit:
This was due to my PS1 Variable being jacked up (refer to answer section for solution).
Issue:
It seems that I am missing a serious concept of the shell builtin bind:
Mac Shell: ~/> $ bind '"4~":"for x in $(); do blah; done"'
# This is my F12 key
Mac Shell: ~/> $ fx in $(); do blah; doneor
This serves no purpose for me other than learning how to use bind.
Note: The or in for along with the ::space:: following for ends up going to the end of the line.
Question:
Can anybody point me in the correct direction as to what I am doing wrong? I checked man bash # shell builtin section and man bind to no avail.
Bash version:
Mac Shell: ~/> $ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin14)
Copyright (C) 2007 Free Software Foundation, Inc.
Thanks for your time!
This was being caused due to improperly quoted ANSI color schemes in my PS1 variable. Essentially I needed \[ & \] around each color code to prevent a miscalculation of bash prompt length.
Thanks everyone for attempting to help me with this issue.

How can I debug the Bourne Shell with gdb?

I built a toolchain script to prepare a Linux build environment. The script can be found here: https://github.com/mynameismevin/prometheus/blob/toolchain/ptool-make.sh
The script runs perfectly until after the Perl section around line 416. After Perl is done, when it goes to unzip sed, it complains with this error:
tar (child): sed-4.2.2.tar.bz2: Cannot open: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now
However, if I run the sections by hand, it completes without errors. If I split the script into ptool-make1.sh (which ends at Perl) and ptool-make2.sh (which starts at sed) and run them sequentially then they both complete without any issues at all. At this point, I assert the issue isn't with the script, and I would like to debug the shell to see if it's an issue with the shell.
Here are some useful configurations:
user#ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"
user#ubuntu:~$ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
user#ubuntu:~$ ls -lh $(which bash)
-rwxr-xr-x 1 root root 998K Oct 7 2014 /bin/bash
I don't think Ubuntu bash comes with debugging symbols, so I would assume I would have to recompile to include those?
How would I use gdb to debug the shell when I run a script? Or how would I have the shell log to a file while the script runs so I can open it with gdb after it's done? I know how to debug a shell script, I don't want to debug the script, I want to debug the shell.
Edit: It doesn't look like Ubuntu bash comes with debugging symbols out of the box. Reading symbols from bash...(no debugging symbols found)...done.
Edit: $PROMETHEUS is set in my root shell. At the end of Perl cd .. results in the same results a cd $PROMETHEUS/sources/.
Shells come with their own debugging tools. The most simple is running them with -x (bash -x ...script...) which will print each command after variable expansion but before it is executed. That's usually enough to determine the problem.
For more ideas, see How to debug a bash script?
You should also consider to write helper functions to reduce the size of the script to just a few lines. You could move special options to configure or post-build steps into extra files and run them from the helper function if they exist.
Looking at the code, it seems that this line is the culrit:
cd $PROMETHEUS/sources/
everywhere else, you just use cd ... If PROMETHEUS isn't defined (the script doesn't define it, that becomes cd /sources/ which should also fail but doesn't abort your script. Try
cd $PROMETHEUS/sources/ || exit 1
instead. Also #!/bin/bash -u might be useful (abort on undefined variables).
Lastly, you can use pushd and popd to navigate the folders.

Resources