8 ms·
I can’t imagine what BASH_ARGV0 is for. Can someone more sage supply an example of what problem it solves?
by BurritoAlPastor 8y ago
I can’t imagine what BASH_ARGV0 is for. Can someone more sage supply an example of what problem it solves?
- spoondan 8y agoThe “set” command lets you override the positional arguments but starting at $1. You cannot directly set $0. But you can set BASH_ARGV0, and the value of $0 changes accordingly.
- mturmon 8y ago“BASH_ARGV0: a new variable that expands to $0 and sets $0 on assignment.” Changing argv[0] would make utilities like ps show a more descriptive/shorter name, eg in the case of long command paths.
- dualbus 8y agoI don't think changing argv[0] in the current process will have any effect in the /proc file system. And to do what you describe, there's `exec -a NAME' already: $ (exec -a NOT-BASH bash -c 'echo $0; ps -p $BASHPID -f') NOT-BASH UID PID PPID C STIME TTY TIME CMD dualbus 18210 2549 0 19:30 pts/1 00:00:00 NOT-BASH -c echo $0; ps -p $BASHPID -f
- LukeShu 8y ago> I don't think changing argv[0] in the current process will have any effect in the /proc file system. Yes it does. This is a standard trick for changing the process name at runtime, several daemons do this to change the process name of child processes created by fork() that aren't separate executable. For instance, OpenSSH's sshd sets the child-process for a session to "sshd: USERNAME [priv]". `exec -a` lets you set argv[0] through an execve() call, but many times you want to set it without exec'ing a new program.
- chrisseaton 8y ago> I don't think changing argv[0] in the current process will have any effect in the /proc file system. Yes it does - that’s the whole point of changing it.
- dualbus 8y agoI would like to understand how this would work. argv is a buffer in Bash's process memory space. This is AFAIK, not shared in any way with the kernel. How would the kernel know that a process wrote to the memory location of argv[0] and then reflect that in /proc? This is what I tried: dualbus@system76-pc:~/src/gnu/bash$ ./bash -c 'echo $BASH_VERSION; ps -p $BASHPID -f; BASH_ARGV0=NOT-BASH; echo $0; ps -p $BASHPID -f; (ps -p $BASHPID -f && : do not optimize fork)' 5.0.0(1)-rc1 UID PID PPID C STIME TTY TIME CMD dualbus 27918 20628 0 20:16 pts/5 00:00:00 ./bash -c echo $BASH_VERSION; ps -p $BASHPID -f; BASH_ARGV0=NOT-BASH; echo $0; ps -p $BASHPID -f; (ps -p $BASHPID -f && : do not optimize fork) NOT-BASH UID PID PPID C STIME TTY TIME CMD dualbus 27918 20628 0 20:16 pts/5 00:00:00 ./bash -c echo $BASH_VERSION; ps -p $BASHPID -f; BASH_ARGV0=NOT-BASH; echo $0; ps -p $BASHPID -f; (ps -p $BASHPID -f && : do not optimize fork) UID PID PPID C STIME TTY TIME CMD dualbus 27921 27918 0 20:16 pts/5 00:00:00 ./bash -c echo $BASH_VERSION; ps -p $BASHPID -f; BASH_ARGV0=NOT-BASH; echo $0; ps -p $BASHPID -f; (ps -p $BASHPID -f && : do not optimize fork)
- chrisseaton 8y agoAny process can write into the argv they get from the kernel. The kernel doesn’t need to monitor for reads - when proc reads it it’s read from the process. It doesn’t need to be specially ‘shared’ with the kernel. The kernel can of course ready any memory it wants to from the process at any time. I’ve implemented setting argv[0] in another language myself.
- dualbus 8y agoCan you show an example of how this would work with BASH_ARGV0?
- LukeShu 8y agoA use-case I've long wanted it for is better "--help" messages. If you want to tell the user how to invoke the program again, argv[0] is the right thing: Given: #include <stdio.h> int main(int argc, char *argv[]) { printf("Usage: %s [OPTIONS]\n", argv[0]); return 0; } Running it as `./dir/demo --help` gives: Usage: ./dir/demo [OPTIONS] Put it somewhere in $PATH, and run it as `demo --help`, and it will give: Usage: demo [OPTIONS] Perfect! But with a Bash script, argv[0] is erased, it sets $0 is set to script path passed to `bash` as an argument. Given: #!/bin/bash echo "Usage: $0 [OPTIONS]" Running it as `./dir/demo --help` gives: Usage: ./dir/demo [OPTIONS] So good, so far, since the kernel ran "/bin/bash ./dir/demo --help". But once we get $PATH involved, $0 stops being useful, since the path passed to Bash is the resolved file path; if you put it in /usr/bin, and run it as `demo --help`, it will give: Usage: /usr/bin/demo [OPTIONS] Because the call to execvpe() looks at $PATH, resolves "demo" to "/usr/bin/demo", then passes "/usr/bin/demo" to the execve() syscall, and the kernel runs "/bin/bash /usr/bin/demo --help". In POSIX shell, $0 is a little useful for looking up the source file, but isn't so useful for knowing how the user invoked you. In Bash, if you need the source file, you're better served by ${BASH_SOURCE[0]}, rendering $0 relatively useless. And neither has a way to know how the user invoked you... until now. It's a small problem, but one that there was no solution for.
- ajross 8y ago> If you want to tell the user how to invoke the program again, argv[0] is the right thing Some pedantry: it's actually not. The argv array is a completely arbitrary thing, passed by the caller as an array of strings and packed by the kernel into some memory at the top of the stack on entry to main(). It doesn't need to correspond to anything in particular, the use of argv[0] as the file name of the program is a side effect of the way the Bourne shell syntax works. The actual file name to be executed is a separate argument to execve(). In fact there's no portable way to know for sure exactly what file was mapped into memory by the runtime linker to start your process. And getting really into the weeds there may not even be one! It would be totally possible to write a linker that loaded and relocated an ELF file into a bunch of anonymous mappings, unmapped itself, and then jumped to the entry point leaving the poor process no way at all to know where it had come from.
- tobylane 8y ago>The purpose of set0 in the debugger is that users often write programs that refer to $0. For example to display a usage string or maybe they change the behavior based on how they were called. So this helps in making these programs act the same way and gives an alternative to invoking with "bash --debugger". https://lists.gnu.org/archive/html/bug-bash/2008-09/msg00054.html https://lists.gnu.org/archive/html/bug-bash/2008-09/msg00054... Yes, 2008.