[HN Gopher] What am I running inside my bash? (2014) ___________________________________________________________________ What am I running inside my bash? (2014) Author : pimterry Score : 114 points Date : 2021-01-28 16:59 UTC (6 hours ago) (HTM) web link (www.thanassis.space) (TXT) w3m dump (www.thanassis.space) | spiznnx wrote: | I usually launch persistent one liners inside a `bash -c | "while...`, just so if it starts using resources I can easily see | what is the original purpose in the process tree. | coldtea wrote: | > _Heck, there has to be a way to get to that line. ps aux | grep | ... doesn 't help - it shows the currently running piece of the | command you wrote. You want the whole shebang._ | | Huh? Why wouldn't it show the original command, since it is still | running? There's also an option to print the "tree" of commands | (e.g. the original command to run some script, other programs | started from said script, etc.) | segfaultbuserr wrote: | Unless you are running the command via "sh -c", you can't see | any shell builtin commands or Unix pipelines by dumping the | process tree. For example, "cat > /dev/null", the redirection | is done by the shell and isn't passed to cat's "char **argv", | in the process tree you can only see a "cat" running without | arguments (and a shell built-in is invisible). It also gives no | information about the control flow of your one-liner shell | script (e.g. what does the "for loop" do?), nor environmental | variables, etc. You can try to reconstruct some information by | inspecting its open files, its environ, etc., but it's not | practical for any complicated combination of commands). | gjvc wrote: | Very clever, but the sensible thing to do is never rely on one- | liners, lest you end up in this kind of situation. Get that | thinking out of your head. Always write the script (that's why | it's called "the script" ... ) in a file and use that. | chubot wrote: | Exactly, I just wrote a blog post about how I do that, | basically with shell scripts in the repo with lots of small | functions. They basically form an annotated log of what I did, | so I never have to remember long commands. | | I can't remember long commands so I always write them down. | | Examples of using a JSON API, using a C++ tool uftrace, and | hacking on Kernighan's awk: | | _Shell Scripts Are Executable Documentation_ | http://www.oilshell.org/blog/2021/01/shell-doc.html | | Admittely there are a lot of people who don't seem to like | reading shell scripts as docs. But you don't really have to | read the code -- you just read the function names. | | I also added doc comments to Oil, like this: | deploy() { ### doc comment cp foo bar | } | | which you can access with the 'pp' builtin. So eventually those | strings could be exposed to autocomplete, etc. | | http://www.oilshell.org/blog/2020/11/more-syntax.html | mr-wendel wrote: | This is why every major project I work on has a | ".archive/oneshot/" folder for anything complicated that was | used to quickly put out a fire. Not only will I inevitably need | to remember months later what happened, but I'll also want to | reuse certain bits later. | | That ".archive" folder itself is then a personal git repo. | Sometimes you just have to put that fire out or get that | question answered and its not worth a "proper" solution, but | keeping a history is worth it. | | Resist the urge to keep it as part of the main project's repo | at all costs. It's far too easy for it to be come standardized | (e.g. by other devs, perhaps) and breath life into them they | should never have. | notorandit wrote: | This is simply old school sys admin mastery. This should | definitely get into school books. It's not the solution itself, | it's the approach. Much like the one in "the martian". Kudos! | ttsiodras wrote: | Thank you for your kind words. The funny thing is that I am not | a sysadmin - or maybe I am one in spirit :-) | ExcavateGrandMa wrote: | The importance of simple prototypes... | | "Is that they are easy to write & re-write from thoughts..." | | :P | Xophmeister wrote: | Why not Ctrl+Z to get back to the prompt and then cursor up to | get the last command? You can `fg` or even `bg` as desired to | resume. | unpythonic wrote: | Because ctrl-z will stop the current command, and when you run | "fg" it resumes that one process. However, the loop you were in | has been abandoned, and it will not continue to execute. | | For example, try it with this: for N in $(seq | 10); do echo $N; sleep 1; echo $N; done | | You'll see something like this: $ for N in | $(seq 10); do echo $N; sleep 1; echo $N; done 1 | 1 2 ^Z [1]+ Stopped | sleep 1 $ fg sleep 1 $ | [deleted] | indigodaddy wrote: | So ctrl-c and up arrow wouldn't work? | ttsiodras wrote: | After so many months, I had no idea what tools I was | running in that command line... And therefore, the effect | of any signal seemed far more dangerous to me, than | extracting the actual command from my shell's memory. | indigodaddy wrote: | Ok I get that | wnoise wrote: | In zsh, it resumes the entire loop. | mr-wendel wrote: | Great point. | | Also, you may have things talking to external resources that | are sensitive to timeouts ... even small ones. You may not be | able to cleanly resume execution and cause an entirely new | problem. | ekimekim wrote: | I'm surprised gdb wouldn't automatically consult /proc/PID/exe to | read symbols. It seems more reliable than checking argv[0] and | then reading the file at that path. | bobbyi_settv wrote: | Maybe it's for portability. The /proc filesystem doesn't exist | on every OS supported by gdb. | kelnos wrote: | Sure, but I'm sure there are tons of Linux-specific things in | gdb behind #ifdefs already; this seems like a pretty | worthwhile thing that justifies adding one more. | m4r35n357 wrote: | er, top | segfaultbuserr wrote: | I'll simply ask gdb to dump its memory, then I extract my command | from its coredump. For example, $ bash | $ echo $$ 477609 $ while true ; do echo 1 ; echo | 2>/dev/null ; sleep 30 ; done # From now on, | this command cannot be stopped, and by now # the text has | been overwritten by new output... | | Open a root shell, install gdb. # gcore 4077609 | 0x00007ae1b321ceca in wait4 () from /lib64/libc.so.6 | Saved corefile core.4077609 [Inferior 1 (process 4077609) | detached] # strings core.4077609 | grep while | ......(omit huge amount of text)...... while true ; do | echo 1 ; echo 2>/dev/null ; sleep 30 ; done | | Studying the source code and calling C functions in a debugger, | like the author did here, is a clever and accurate way to solve | this problem and deserves its pages in sysadmin folklore, but I | think my brute-force approach, although boring, is equally | acceptable. It's also safer, a wrong function call won't crash | the program. If I can not find what I need immediately, analyzing | the coredump safely in a debugger (perhaps on my own machine with | more devtools installed, with a cup of tea) is also an option for | me. | jcynix wrote: | Modern shells are powerful enough to help you remember, if you | learn to configure them appropriately. My histories are always | saved because each shell instance gets its own HISTFILE, like so: | export HISTFILE=$HOME/.history/${TTY##\*/}.$SHLVL | | As I use different terminal windows for different tasks, this | keeps history files rather concise thematically. | | And I let the shell add timestamps too, so I can grep for entries | produced during a certain time span: | | zsh: setopt EXTENDEDHISTORY # add timestamps | | bash: HISTTIMEFORMAT="%F %T " | | I write perl or shell script files, of course, if it's more than | some a handful of lines. | amelius wrote: | Can you also add the working directory in which each command | was run? | jcynix wrote: | You could deduce the working directory from the sequence of | commands in your history file, so the working directory is | implicitly contained in the history file. | | I don't remember an option to save the working directory | explicitly. But zsh has a number of history related commands, | which can be used to execute shell functions before and after | each command. So you could use these to write your own | special history file, even one per directory if need. | Example: zshaddhistory () { echo "$PWD -- | $1" >> $MY_HISTFILE } | | This shell function defined here will run when the command | has been read but just before it will be executed. The | argument $1 contains the command line to be executed. | [deleted] | aidenn0 wrote: | Does bash have an option to write out the history _before_ | running the command? Usually history is written in | PROMPT_COMMAND, which runs after the command completes. | jcynix wrote: | I don't know about bash, but zsh allows you to define a shell | function "zshaddhistory" which is running right before a | command is executed. | joombaga wrote: | Not exactly, but there's $PS0 if you have bash 4.4+. | | https://stromberg.dnsalias.org/~strombrg/PS0-prompt/ | | (Thanks Dan!) | nickodell wrote: | Why couldn't you attach to the screen, press Ctrl-C, then press | up arrow to get the original command? | ttsiodras wrote: | The script was running in production, doing actual work. | Stopping it - when you don't remember a damn thing about it and | how it worked - was not an option I wanted to consider at the | time. | Skunkleton wrote: | or ctrl-z for that matter | ttsiodras wrote: | The answer to that is simpler: Try doing the Ctrl-z/fg | sequence in your bash with this one: while | true ; do sleep 1 ; done | | You'll see that after 'fg', the loop ends :-) | | Simply put: C-z followed by fg is not bulletproof. Not to | mention that I had no idea what I was running in there, and | how any signal would impact it... So I wanted to find a safer | way to dump what was already there, in my shell's memory. | | Anyway, I hope you guys enjoyed reading this regardless :-) ___________________________________________________________________ (page generated 2021-01-28 23:01 UTC)