/bin/sh should set SHELL to /bin/sh
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-redhat-linux-gnu' -DCONF_VENDOR='redhat' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -D_GNU_SOURCE -DRECYCLES_PIDS -DDEFAULT_PATH_VALUE='/usr/local/bin:/usr/bin' -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic uname output: Linux f25e64.local 4.11.7-200.fc25.x86_64 #1 SMP Mon Jun 26 15:58:22 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-redhat-linux-gnu Bash Version: 4.3 Patch Level: 43 Release Status: release Description: When invoked as /bin/sh with SHELL unset, then bash should set SHELL to /bin/sh, not to the login shell for the current user. The current behavior can lead to surprises when descendants of /bin/sh invoke $SHELL. There is even a reasonable argument that /bin/sh _always_ should set SHELL=/bin/sh, even (and especially) overriding an existing SHELL=/bin/bash. This would agree with the manual page: "SHELL: The full pathname to the shell is kept in this environment variable." If it's not going to change, then please emphasize the current behavior on the manual page: "SHELL: ... If it is not set when the shell starts, bash assigns to it the full pathname of the current user's login shell, even if the result is SHELL=/bin/bash but the current shell was invoked as /bin/sh." Repeat-By: # Verify that /bin/sh is a link to bash. $ ls -l /bin/sh lrwxrwxrwx. 1 root root 4 Sep 30 2016 /bin/sh -> bash # Remove SHELL from the environment, invoke /bin/sh, # ask for the new value of SHELL. # Note the single quotes to prevent expansion before invoking /bin/sh. $ env --unset=SHELL /bin/sh -c 'echo $SHELL' /bin/bash # Be pedantic: verify the comments above $ strace -e trace=execve -v -s 100 env --unset=SHELL /bin/sh -c 'echo $SHELL' execve("/usr/bin/env", ["env", "--unset=SHELL", "/bin/sh", "-c", "echo $SHELL"], [..., "SHELL=/bin/bash", ...] execve("/bin/sh", ["/bin/sh", "-c", "echo $SHELL"], [..., /* no SHELL= */, ...] Fix: Special case the setting of SHELL when the current shell was invoked as /bin/sh. --
Re: Debugging memory usage
> I took a look and saw the bash process consuming as much as 3+ GB of > memory. I'm not doing anything where I'd expect to be consuming that > much memory. As a workaround, try using "ulimit -v" to restrict the virtual memory space of the shell itself. (For invoking some child processes, it may be necessary to use an intermediate shell which raises the limit before exec-ing the child.) It is not uncommon for a process (not just bash) to allocate until refused, and only then think about free()ing or collecting garbage. --
Re: Obsolete SIGRTMAX-n signal names
On 05/29/2013 01:35 AM, Harald Hoyer wrote: > On 04/24/2013 05:26 PM, Chet Ramey wrote: >> On 4/23/13 2:05 AM, Harald Hoyer wrote: >>> As reported in http://savannah.gnu.org/patch/?8025 , I would like to see the >>> SIGRTMAX-n signal names disappear. >>> >>> Signals should never ever be addressed with SIGRTMAX-n. Signals should >>> always be >>> addressed with SIGRTMIN+n. >> >> I'll take a look at this, but that's a pretty strong statement to make from >> something that appears in one Linux man page. I can't find any shell in my >> quick testing that behaves as you propose. Is there any other reason to do >> this? >> >> Chet >> >> > > Any progress, comments? Comment: In practice SIGRTMIN is a very stable value. For each architecture SIGRTMIN is chosen at the time of the original port, and after that SIGRTMIN "never" will change, although in theory it could. The value of SIGRTMAX is less stable because it changes whenever _NSIG changes. _NSIG has changed from 32 to 64, and in some cases has reverted to 32 in order to save 4 bytes [or 4*sizeof(void *)] in various places, and to make code smaller and simpler [because (32/8)==sizeof(unsigned int)]. --
Re: How to match regex in bash? (any character)
Peng Yu wrote: > I know that I should use =~ to match regex (bash version 4). > > However, the man page is not very clear. I don't find how to match > (matching any single character). For example, the following regex > doesn't match txt. Does anybody know how to match any character > (should be '.' in perl) in bash. > > [[ "$1" =~ "xxx.txt" ]] The manual page for bash says that the rules of regex(3) apply: An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)). The return value is 0 if the string matches the pattern, and 1 otherwise. and also: Any part of the pattern may be quoted to force it to be matched as a string. Thus in the expression [[ "$1" =~ "xxx.txt" ]] the fact that the pattern is quoted [here the whole pattern appears within double quotes] has turned the dot '.' into a plain literal character, instead of a meta-character which matches any single character. The usual method of avoiding quotes in the pattern is to omit them: [[ $1 =~ xxx.txt ]] # the dot '.' in the pattern is a meta-character or to use a variable: pattern="xxx.txt" # a 7-character string [[ $1 =~ $pattern ]] # the dot '.' in $pattern is a meta-character Example: using all literals in an instance of bash: $ [[ txt =~ xxx.txt ]] && echo true true $ Also notice that quotes are not needed around the left-hand side $1 : Word splitā ting and pathname expansion are not performed on the words between the [[ and ]] ... Thus there is no need to use quotation marks to suppress word splitting inside double brackets [[ ... ]]. --
RFE: indirection_level_string() preserves 'x' flag [PATCH]
Please enhance the function indirection_level_string() in print_cmd.c so that the value of the 'x' flag is preserved over the call to decode_prompt_string(). This will permit the use of function indirection_level_string() as a tool to track usage of system calls by shell scripts. For example, this code prints the script location of every fork(). - // bash-syspose.c - interpose so that bash shell prints $PS4 upon syscall // Copyright 2011 John Reiser, BitWagon Software LLC. All rights reserved. // Licensed under GNU General Public License, version 3 (GPLv3). // // Requires: change indirection_level_string() in bash/print_cmd.c //to preserve 'x' flag around decode_prompt_string(): /* --- bash-4.2/print_cmd.c2011-09-08 13:27:53.877244584 -0700 +++ new/print_cmd.c 2011-09-08 13:29:34.088991764 -0700 @@ -426,9 +426,9 @@ if (ps4 == 0 || *ps4 == '\0') return (indirection_string); - change_flag ('x', FLAG_OFF); + int const old = change_flag ('x', FLAG_OFF); ps4 = decode_prompt_string (ps4); - change_flag ('x', FLAG_ON); + if (old) change_flag ('x', FLAG_ON); if (ps4 == 0 || *ps4 == '\0') return (indirection_string); */ // Build: gcc -shared -o bash-syspose.so -g -O -fPIC bash-syspose.c // Run: LD_PRELOAD=./bash-syspose.so bash ... # "unset LD_PRELOAD" ASAP! // EXAMPLE: (insert near beginning of shell script) // unset LD_PRELOAD // export PS4=' ${FUNCNAME[0]}@$LINENO < ${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]} :' // // Obviously other syscalls could be handled, too. #define _GNU_SOURCE 1 /* need RTLD_NEXT from dlfcn.h */ #include #include #include // weak: Test to prevent crash if no such function, such as when // LD_PRELOAD remains set and a child process of bash invokes a // random executable that does a fork(). extern char const *indirection_level_string(void) __attribute__((weak)); int fork(void) { static int (*real_fork)(void); if (!real_fork) real_fork = (int (*)(void)) dlsym(RTLD_NEXT, "fork"); // Avoid infinite recursion in case evaluating PS4 does a fork(). static int recur; char const *ils = 0; if (!recur++ && indirection_level_string) { ils = indirection_level_string(); // evaluate $PS4 } if (!--recur && ils) { write(2, ils, strlen(ils)); write(2, "fork\n", 5); } // The child might want to remove us (bash-syspose) from LD_PRELOAD. // But it is ugly, so rely on 'weak' for now. return (*real_fork)(); } // end-of-file bash-syspose.c - --
Re: How to input ^J?
> Lastly since ^J is a newline you can generate one with echo "\n". That does not work in bash-4.x. Firstly, by default the bash builtin 'echo' supplies a trailing newline. Secondly, backslash translation requires the option "-e". $ echo "\n" \n $ echo "\n" | od -c 000 \ n \n 003 $ What does work is either of these: $ echo '' | od -c 000 \n 001 $ echo -e -n '\n' | od -c 000 \n 001 $ --
Re: Set of characters that are treated specially between a pair of double quotes?
> Could anybody let me know the complete set of characters that need to > be escaped (prepend with backslash) between a pair of double quotes if > I really want to print the character? RTFM. In particular, the manual page ("man bash") has a succinct section entitled "QUOTING". --
Re: How to input tab in command line?
> I have command completion in my bash command. But I need to input tab > in the command line. Is there a way to do so? Quote the with V. $ echo ' ' | od -c # e c h o V 000 \t \n 002 $ echo '' | od -c # e c h o 000 \n 001 $ --
Re: A note for read builtin
On 06/18/2010 07:05 AM, Dr. Werner Fink wrote: > Just a remark about the sub shell usage in bash in comparision to > ksh. Let's try: > > strace -f -o bash.strace bash -c 'echo a b | read a b' > > grep -E 'execve|clone|write\(1|read\(0' bash.strace [snip] > > and now the same with the Korn shell > > strace -f -o ksh.strace ksh -c 'echo a b | read a b' > > grep -E 'execve|clone|write\(1|read\(0' ksh.strace | sed 's/^//' [snip] > > as now is visible the last command in the pipe sequence done > in the bash is a real sub process whereas in the ksh it is not. > > The question rises: Why does the bash require a sub peocess/shell > for the final command of a pipe sequence. Running strace -f -o ksh.strace ksh -c 'echo a b | cat' shows that ksh requires a subprocess/shell for the 'cat' which is the final command in _that_ pipe sequence. Apparently ksh knows when the final command in a pipe sequence is a shell builtin, then omits the subprocess in that case. Could bash's $PIPE_STATUS[] or related issues about control, environment, and history ("trap", etc.) be relevant here? --
Re: [bash-bug] Can arithmetic evaluation trap more than just division by zero?
Program received signal SIGFPE, Arithmetic exception. 0x00462cd5 in exp2 () at expr.c:761 761 val1 /= val2; (gdb) print val1 $1 = -9223372036854775808 (gdb) print val2 $2 = -1 which is strange. Not at all. Overflow invokes undefined behaviour. But why there is no overflow on 32bit system? No *detected* overflow. For instance, if computing (2 ** 63) gives 0 (the low-order 32 bits of the true result) and does not detect the overflow (or ignores the overflow, either by intention or by bug), then there is no problem with computing (0 / -1). --
Re: Mixing exec redirection with explicit redirection, unexpected results
#!/bin/bash > /tmp/foo exec 1>/tmp/foo echo a echo B>>/tmp/foo echo c echo D>>/tmp/foo echo e echo F>>/tmp/foo That script creates two simultaneous writers of /tmp/foo (one via the "exec >", another via each "echo >>") but does not provide any concurrency control. Shame on the script; the results are undefined. The only possible legitimate complaint _might_ be that bash did not detect and warn about the user error. The fix is to provide some concurrency control, or not to create multiple simultaneous writers of the same file. Because all output is going to the same file, then the simplest solution is to omit all the appending ">>/tmp/foo" because they are subsumed by the initial redirection "exec >/tmp/foo". Perhaps concurrency control can be provided by using a fifo: mkfifo /tmp/my_fifo cp /tmp/my_fifo /tmp/foo & # constantly drain the fifo exec >/tmp/my_fifo echo a echo B >>/tmp/my_fifo etc. However, this relies upon bash _not_ buffering the first redirection, and that is not guaranteed. Bottom line: avoid simultaneous writers of the same file. --
Re: slight OT: shell-script programing style -- origins and change?
... the age old convention of using upper case names for all their shell variables. ... It reminds some programmers that a '$' is necessary for expansion. It is somewhat like using all capitals for #define macros in C (where the expansion is automatic, but still different from other symbols that aren't macro names.) Both of these are surreptitious salves for not having the full LISP conventions for eval and quote. --
Re: preventing pipe reader from existing on writer exiting
Ultimately I need to do I/O through a named pipe and I need to be able to restart the writer without restarting the reader. The reader of a fifo will not be terminated as long as there is at least one writer to the fifo. Therefore, create a second writer. For example, to hold the fifo open for one hour: sleep 3600 > /tmp/fifo & The shell forks, then opens /tmp/fifo for writing. The open() waits until there is a reader. Then the forked shell execs /bin/sleep, which waits for 3600 seconds before exiting. During that 3600 seconds the fifo is open for writing, so the system will not terminate any reader of the fifo for at least that long. --
Re: Bash does not read up the whole script which it is currently executing
On 08/04/2009 12:48 AM, fam...@icdsoft.com wrote: First I would like to say that I'm not sure if this is a bug or a feature of Bash. If it is a feature, please let me know how to turn it off; or better make it disabled by default... The problem is that Bash does not read up the whole script which it is currently executing. As a result of this, if we update the script file with a newer version while it is running, this may lead to unpredicted results. It is an intended design feature that the shell reads only as much as necessary to proceed at the moment. This is required so that subprocesses can share the same stdin as the shell. Bytes for input to the shell alternate with bytes for input to each subprocess that does not have redirection (or closure) specified for its stdin. To avoid this feature, then use the "-c" parameter to specify the entire shell input as a string on the command line: bash -c "$(< filename)" Or, make a temporary unique copy of the file, then invoke the shell on the copy. --
omit fork before last exec
Hi, Would it be possible for bash to detect just-in-time the last subprocess that it will execute, and then do only an 'execve' instead of a fork+execve? This might save a lot of operating system overhead for process creation: perhaps upto 10% over the course of a day, especially for most uses of 'make'. It seems to me that this could work if there are no active traps and if the shell's input can be re-positioned without penalty. An active trap might get triggered by the supposed last subprocess; then interpreting the body of the trap could invalidate the "last subprocess" property. If the shell's input cannot be repositioned (is not a regular file or "-c" command line string; is a pipe, socket, fifo, character device, etc.) then lookahead on the shell's input is problematic. Lookahead is necessary to determine the "last subprocess" property. However, the lookahead must be undone before exec so that semantics remain the same for the case when the shell and a subprocess share the input stream. Piping input into a shell often relies on alternating consumption of the piped input by the shell and one or more subprocesses that have un-redirected stdin. Comments? --