BREAKING change trackrun record file format; improve trackrun
[hband-tools.git] / user-tools / trackrun
blobeac1d57c0867bc44d11859ef57df3486981a61b2
1 #!/bin/bash
3 set -e
4 set -o pipefail
5 set -u
8 true <<'EOF'
10 =pod
12 =head1 NAME
14 trackrun - Record when the given command was started and ended and expose to it in environment variables
16 =head1 SYNOPSIS
18 trackrun [I<OPTIONS>] [--] I<COMMAND> [I<ARGS>]
20 =head1 DESCRIPTION
22 It records when it starts COMMAND and when it ends, identifying COMMAND either by one of 4 options:
24 =over 4
26 =item Full command line including I<ARGS>.
28 =item Only the command name, I<COMMAND>.
30 =item By the name given by the user in I<NAME>.
32 =item By the environment variable value given by name I<ENV>.
34 =back
36 Set B<TRACKRUN_LAST_STARTED> and B<TRACKRUN_LAST_ENDED> environments for COMMAND to the ISO 8601 representation
37 of the date and time when COMMAND was last started and ended respectively.
38 Set B<TRACKRUN_LAST_STATUS> to the status COMMAND last exited with.
39 Those are left empty if no data yet.
41 On every run, a UUID is generated, so you can connect events of concurrent runs in the track report.
42 It is exposed in B<TRACKRUN_UUID> env.
44 =head1 OPTIONS
46 =over 4
48 =item -f, --full-command
50 =item -b, --command-basename (default)
52 =item -n, --name I<NAME>
54 =item -e, --env-var I<ENV>
56 =item -h, --show-hash
58 Show the hash generated from either of those options above before run the I<COMMAND>.
59 This hash is used for the filename in which command-related events are stored.
61 =item -u, --show-uuid
63 Show the current run's UUID before actually start the command.
65 =item -U, --write-uuid I<FILE>
67 Write current run's UUID in the given file before start the command.
69 =item -R, --report
71 Do not run I<COMMAND>, instead display its tracked history.
73 =back
75 =head1 FILES
77 Store tracking data in F<~/.trackrun> directory.
79 =head1 ENVIRONMENT
81 =over 4
83 =item TRACKRUN_LAST_STARTED
85 =item TRACKRUN_LAST_ENDED
87 =item TRACKRUN_LAST_STATUS
89 =item TRACKRUN_UUID
91 =back
93 =head1 LIMITATIONS
95 Trackrun does not do locking. You may take care of it if you need using flock(1), cronrun(1), or similar.
97 =cut
99 EOF
102 cmd_id=''
103 cmd_id_by=basename
104 do_report=''
105 uuid_outfile=''
106 do_show_hash=''
107 do_show_uuid=''
110 while [ $# -gt 0 ]
112 case "$1" in
113 --help)
114 pod2text "$0"
115 exit 0;;
116 -f|--full-command)
117 cmd_id_by=full
119 -b|--command-basename)
120 cmd_id_by=basename
122 -n|--name)
123 cmd_id_by=name
124 shift
125 cmd_id=$1
127 -e|--env-var)
128 cmd_id_by=env
129 shift
130 cmd_id=${!1}
132 -R|--report)
133 do_report=1
135 -h|--show-hash)
136 do_show_hash=1
138 -u|--show-uuid)
139 do_show_uuid=1
141 -U|--write-uuid)
142 shift
143 uuid_outfile=$1
146 shift
147 break;;
149 echo "$0: unknown option: $1" >&1
150 exit -1;;
152 break;;
153 esac
154 shift
155 done
158 if [ $# = 0 ]
159 then
160 pod2text "$0" >&2
161 exit -1
165 declare -a cmd_args=("$@")
168 if [ -z "$cmd_id" ]
169 then
170 case "$cmd_id_by" in
171 full)
172 cmd_id=${cmd_args[*]}
174 basename)
175 cmd_id=`basename "${cmd_args[0]}"`
177 esac
181 track_dir=~/.trackrun
182 cmd_id_hash=`printf %s "$cmd_id" | md5sum | cut -c 1-32`
183 track_file=$track_dir/$cmd_id_hash
186 if [ $do_report ]
187 then
188 cat "$track_file" | tac | td-add-headers UUID EVENT DATETIME STATUS COMMAND
189 exit
193 lookup()
195 # lookup A B C
196 # return the C-th field of the first line in stdin of which A-th field is B
197 awk -F $'\t' -v field_num="$1" -v field_val="$2" -v field_ret="$3" \
198 '{if($field_num == field_val){ print $field_ret; exit; }}'
201 mkdir -p "$track_dir"
202 export TRACKRUN_LAST_STARTED=`tac "$track_file" 2>/dev/null | lookup 1 start 3`
203 export TRACKRUN_LAST_ENDED=`tac "$track_file" 2>/dev/null | lookup 1 end 3`
204 export TRACKRUN_LAST_STATUS=`tac "$track_file" 2>/dev/null | lookup 1 end 4`
206 type uuidgen >/dev/null
207 export TRACKRUN_UUID=`uuidgen`
209 if [ $do_show_uuid ]
210 then
211 echo "${0##*/}: command run uuid: $TRACKRUN_UUID" >&2
213 if [ -n "$uuid_outfile" ]
214 then
215 echo "$TRACKRUN_UUID" > "$uuid_outfile"
218 record()
220 printf "%s\t%s\t%(%FT%T%z)T\t%s\t%s\n" "$TRACKRUN_UUID" "$1" -1 "${2:-}" "${cmd_args[*]}" >> "$track_file"
223 record start
226 exec -- setsid ${cmd_args[@]}
227 exit 127
230 child_pid=$!
231 signal_handler() { interrupted=yes; }
232 trap signal_handler INT
233 while true
235 interrupted=''
236 set +e
237 wait $child_pid
238 exit_code=$?
239 set -e
240 if [ $interrupted ]
241 then
242 exit_code=''
243 kill -s INT $child_pid || true
244 else
245 break
247 done
249 record end $exit_code
251 exit $exit_code