| Crates.io | si-loggy |
| lib.rs | si-loggy |
| version | 0.1.0 |
| created_at | 2024-06-26 07:37:49.437471+00 |
| updated_at | 2024-06-26 07:37:49.437471+00 |
| description | Automatic logging & nohup for arbitrary commands |
| homepage | |
| repository | https://github.com/Standard-Intelligence/loggy |
| max_upload_size | |
| id | 1284244 |
| size | 34,182 |
loggyloggy wraps commands and automatically tees their output to log files without modifying original programs or scripts.
tee without the need to specify a namesudo -E "$(command -v cargo)" install --root /usr/local si-loggy
sudo -E "$(command -v cargo)" install --root /usr/local --git https://github.com/Standard-Intelligence/loggy
Wrap a command with loggy to log its output:
$ loggy echo hello world
[loggy] logging to /home/robert/logs/echo-0.log
hello world
Or, pipe a command to loggy:
$ echo hello world | loggy
[loggy] logging to /home/robert/logs/loggy-14.log
hello world
Wrapping a command (i.e. running loggy command or using one of the below methods) is preferable to piping to loggy because loggy can handle SIGHUP and closed stdout/stderr (such as from a detached terminal) on behalf of wrapped processes.
Symlink loggy to each program to log:
ln -s /usr/local/bin/loggy /usr/local/bin/pip
ln -s /usr/local/bin/loggy /usr/local/bin/python
ln -s /usr/local/bin/loggy /usr/local/bin/python3
When a wrapped program is run, loggy creates a log file in ~/logs based on the command name and any arguments corresponding to existing files:
$ pip install -r requirements.txt
[loggy] logging to /home/user/logs/pip-requirements.txt-0.log
If the wrapped program produces no output (e.g. loggy true), no log file is created.
loggy can be temporarily disabled for a wrapped command by setting the NO_LOGGY environment variable (to any value except 0):
NO_LOGGY= python3 -m print-all-my-secrets
For loggy to handle broad patterns that could occur in any command (such as the /sandbox example below), it must run for every command (at which point a config file determines which commands are actually logged). Add this to your .bashrc to run every command under loggy:
loggy() {
if [[ -v AT_PROMPT ]]; then
unset AT_PROMPT
local t="$(type -t $@)"
if [[ "$t" == "file" ]]; then
command loggy $@
shopt -s extdebug
return 1
elif [[ "$t" == "function" ]]; then
$@
shopt -s extdebug
return 1
fi
fi
}
unset -f command_not_found_handle
trap 'loggy ${BASH_COMMAND}' DEBUG
PROMPT_COMMAND="shopt -u extdebug; ${PROMPT_COMMAND}; AT_PROMPT="
By default, loggy creates logs for anything it wraps. You may want finer control than symlinks and NO_LOGGY offer, e.g. to log only invocations of a certain Python module. As a last resort, loggy loads a list of regular expressions from the first existing file out of ~/.config/loggy and /etc/loggy. If one of these files exists, and a command is wrapped by loggy, it will be logged if and only if it matches one of the regular expressions from the config file.
Example configuration:
# Log `make` commands with any arguments
^make( |$)
# Log all Python scripts, but not e.g. `python -m pip`
^([^ ]*/)?(python3?|python-[0-9.]+) .*\.py\b
# Log invocations of a specific Python module
^([^ ]*/)?(python3?|python-[0-9.]+) -m ?torch\.distributed\.run
# Log any commands involving the /sandbox directory
/sandbox
We recommend using config files as a last resort, because writing regex is hard :)
If you've run loggy and then disconnected the terminal or SSH connection, run tail -f ~/logs/example.log in a new terminal to stream its output.
If installed, loggy automatically uses stdbuf to ensure wrapped commands write their output to the terminal and log file line by line instead of with full buffering. Ensure stdbuf is installed for optimal performance.