# Shell integration for shournal
## Basic setup (interactive)
After installation, to start observing your *interactive* shell-sessions
append the following to your shell's rc:
**~/.bashrc**
~~~
HISTCONTROL=ignoredups:erasedups # NOT ALLOWED: ignorespace,ignoreboth
source /usr/share/shournal/SOURCE_ME.bash
SHOURNAL_ENABLE
~~~
**~/.zshrc**
~~~
source /usr/share/shournal/SOURCE_ME.zsh
SHOURNAL_ENABLE
~~~
Launch a new shell afterwards and check whether it's working:
~~~
$ echo foo > bar
$ shournal --query --wfile bar
cmd-id 66075 $?=0 2021-11-02 14:23 $ echo foo > bar
Working directory: /home/tycho
session-uuid 3hIZtDwhEey5WPDVv9W/Cw==
1 written file:
/home/tycho/bar (4 bytes) Hash: 8087352826690557229
$ # or just look into the history:
$ shournal --query --history 3
# ...
~~~
The shell-integration injects code into
`PROMPT_COMMAND`, `PS0` and `PS1` (bash) or the `preexec/precmd_functions`
(zsh), so please do not overwrite those after having enabled shournal.
Further basic history functionality must be available, e.g. in bash
HISTCONTROL must not ignore commands with leading spaces (see above).
shournal's shell integration checks the typical variables and gives
hints, if there is need for action.
Other commands include
`SHOURNAL_DISABLE` to disable the observation
`SHOURNAL_PRINT_VERSIONS` to print the version of each component
`SHOURNAL_SET_VERBOSITY` to change the default verbosity ("dbg, info,
warning, critical"). For dbg, shournal must have been compiled with
debugging symbols. A verbosity higher than *warning* is not recommended.
## Advanced setup (non-interactive)
To also observe non-interactive commands executed via ssh
~~~
ssh localhost echo foo
~~~
or the *Sun Grid Engine* (SGE) the following setup is recommended:
**bash**
Put the following near the **beginning** of your bashrc:
~~~
if [[ -n ${SGE_O_WORKDIR+x} || (
-n ${BASH_EXECUTION_STRING+x} &&
( -n ${SSH_CLIENT+x} || -n ${SSH_TTY+x} )
) ]]; then
source /usr/share/shournal/SOURCE_ME.bash
SHOURNAL_ENABLE
fi
~~~
In particular that code has to run before the sourcing of ~/.bashrc
stops due to a negative interactive-check. For example, some distributions
place the following near the top of the bashrc:
~~~
case $- in
*i*) ;;
*) return;;
esac
~~~
**zsh**
Put the following into ~/.zprofile
~~~
if [[ -n ${SGE_O_WORKDIR+x} || (
-n ${ZSH_EXECUTION_STRING+x} &&
( -n ${SSH_CLIENT+x} || -n ${SSH_TTY+x} )
) ]]; then
source /usr/share/shournal/SOURCE_ME.zsh
SHOURNAL_ENABLE
fi
~~~
Note that depending on your server environment, this requires zsh to be
executed as login shell, e.g.
`ssh HOST zsh -l -c command`. Alternatively
you may use ~/.zshenv but beware that this file is always sourced, also
during `zsh -c ':'` invocations on the interactive command-line, so at least
an additional check for
`[ $SHLVL -eq 1 ]` is recommended.
For cluster software systems other than SGE, you may
`export SHOURNAL_IS_CLUSTERJOB=true`, before `SHOURNAL_ENABLE`, if and
only if the shell is about to execute a cluster job. Note
that in this case, shournal performs a re-execution of the current
command and only returns control flow after flushing the database, because
cluster software systems tend to kill background processes, once the
main job script finished. To totally disable cluster job detection,
set `SHOURNAL_NO_CLUSTER_JOB_DETECT=true` before `SHOURNAL_ENABLE`.
## Prerequisites of the fanotify backend
If the *fanotify* backend is used, please ensure the following:
* The shell must be linked dynamically against (g)libc (default case,
can be tested e.g. with
`file $(which bash) | grep "dynamically linked"` ).
* Sourcing of SOURCE_ME.$shell must be within the shell's rc-file.
* `SHOURNAL_ENABLE` should be within the shell's rc, because
on the very first enable the shell is re-executed, purging all non-exported
variables.
* For non-interactive commands `SHOURNAL_ENABLE` must be called
before the actual execution begins.
Note that the kernel module backend does not have those prerequisites
and should be preferred in most cases.
## Updates
If the shell-integration is running while shournal is updated, it is recommended,
to restart your shell. A more elegant way than logout-login might be to `exec` your $shell.
## FAQ
* **How to obtain the value of variables?**.
If shell-variables are used within a command, shournal's reports might
not seem to be very helpful. However, the shell-integration assigns
each shell-session a unique identifier (uuid).
In the likely case that the variable was
assigned *during that session*, you might be able to obtain its value.
This of course only works, if SHOURNAL_ENABLE was called, *before*
a variable was assigned. Example:
`shournal --query --shell-session-id 'L/932KZTEemRB/dOGB9LOA==' | grep var_name`
* **What about new, nested shell-sessions**?
By *new shell-sessions* it is meant to call e.g. `bash` within an already
running bash-process. What happens next really depends on whether the
shell is itself **observed** by shournal or not (e.g. whether
`SHOURNAL_ENABLE` is within the .bashrc or not). On calling
`SHOURNAL_ENABLE` file-events are then considered to belong to the
new shell-session and are no longer reported to the original
observation-process of the caller. If a **non-observed** shell
is a called, shournal's later report will not be very helpful: all
file-modifications caused by that process will yield the plain
shell-command (and not individual commands possibly entered
within the new shell session).
## Limitations
* File-operations (redirections) which spread over **multiple** command-sequences
within the **interactive shell** might lead to surprising (*kernel module backend*)
or incorrect (*fanotify backend*) results.
Example:
~~~
$ exec 3> /tmp/foo # open fd 3
$ echo "test" >&3
$ exec 3>&- # close fd 3.
~~~
In case of the *kernel module backend* as usual the close event is
tracked, however `shournal -q -wf /tmp/foo` prints only the command
`exec 3>&-`. By using the shell-session uuid it should be possible
to reconstruct those cases.
In case of the *fanotify backend* the close-event is lost.
* **Additional limitations of the fanotify-backend**:
Filesystem-events of asynchronously launched processes, which close the inherited
shournal-socket, might be lost, because an external shournal-run process
waits until all instances of that socket are closed.
Steps to reproduce: In an *observed* shell-session enter
`bash -c 'eval "exec $_SHOURNAL_SOCKET_NB>&-"; sleep 1; echo foo > bar' &`
Note that e.g. in *Python* processes launched via its
*subprocess*-module do not inherit file descriptors by default.
There seems to be no general solution to this problem, but in most cases
there should be some mechanism to wait for the processes to finish,
within the interactive shell-session or a script.
* For further limitations please also read the general
[README](/../../).
## Motivation
For a general introduction about the data and meta-data *shournal* stores
please visit the general [README](/../../).
Having to type *shournal* before every single command one wants
to observe can be tiresome. Another typing-overhead would be
introduced by using pipes or redirections.
Consider the following **broken** example:
shournal --exec echo hi > foo # Don't do this.
As many shell users know the redirection applies to the whole command,
while shournal itself only observes "echo hi". The file modification event ('hi'
written to 'foo')
is hence **not** tracked by shournal.
To actually observe such a command
one must rather type
shournal --exec sh -c 'echo hi > foo'
That's annoying, right?
Therefore before observing one or multiple commands,
`source` the respective integration-file within your shell's rc
(e.g. .bashrc) and type
SHOURNAL_ENABLE
That's (almost) all. Forget about *shournal* until needed
( e.g. you want to know how a certain file was created).