What am I running inside my bash? (2014)
thanassis.space
thanassis.space
$ 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.https://github.com/andikleen/pstrings
I used it a few times to handle similar situations, like recovering text from a web browser.
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.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.I didn't think of that, but I don't think it's always possible. E.g. suppose you run "source somefile", and somefile contains a cd command.
Unfortunately I'm using bash mostly, so I'm afraid the suggestion you gave for zsh doesn't work for me.
By the way, another thing I'm interested in is how people manage their history files over multiple machines.
https://stromberg.dnsalias.org/~strombrg/PS0-prompt/
(Thanks Dan!)
echo "$HOSTNAME $$ $(date "+%Y-%m-%dT%H:%M:%S%z") $*" >> ~/.fullhistory
It's attached to the preexec hook of https://github.com/rcaloras/bash-preexec, so is run before every command. This means that everything goes into one easily-greppable file, but is still separable by PID/host machine - since my work has me walking around a large facility, often I'll remember where I was when I did something but not exactly when, so can narrow down by machine.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.
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.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
$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.
$ <CTRL-z>
$ <CTRL-p>
$ <CTRL-c>
$ fgHuh? 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.)
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 :-)