Linux Command History with date and time - linux

I wants to check on my linux system when which command was fired - at which date and time.
I fired commands like this:
history 50
It shows me the last 50 commands history, but not with date and time at which it was fired. Does any one knows how to do it?

Regarding this link you can make the first solution provided by krzyk permanent by executing:
echo 'export HISTTIMEFORMAT="%d/%m/%y %T "' >> ~/.bash_profile
source ~/.bash_profile

Try this:
> HISTTIMEFORMAT="%d/%m/%y %T "
> history
You can adjust the format to your liking, of course.

In case you are using zsh you can use for example the -E or -i switch:
history -E
If you do a man zshoptions or man zshbuiltins you can find out more information about these switches as well as other info related to history:
Also when listing,
-d prints timestamps for each event
-f prints full time-date stamps in the US `MM/DD/YY hh:mm' format
-E prints full time-date stamps in the European `dd.mm.yyyy hh:mm' format
-i prints full time-date stamps in ISO8601 `yyyy-mm-dd hh:mm' format
-t fmt prints time and date stamps in the given format; fmt is formatted with the strftime function with the zsh extensions described for the %D{string} prompt format in the section EXPANSION OF PROMPT SEQUENCES in zshmisc(1). The resulting formatted string must be no more than 256 characters or will not be printed
-D prints elapsed times; may be combined with one of the options above

It depends on the shell (and its configuration) in standard bash only the command is stored without the date and time (check .bash_history if there is any timestamp there).
To have bash store the timestamp you need to set HISTTIMEFORMAT before executing the commands, e.g. in .bashrc or .bash_profile. This will cause bash to store the timestamps in .bash_history (see the entries starting with #).

HISTTIMEFORMAT="%d/%m/%y %H:%M "
For any commands typed prior to this, it will not help since they will just get a default time of when you turned history on, but it will log the time of any further commands after this.
If you want it to log history for permanent, you should put the following
line in your ~/.bashrc
export HISTTIMEFORMAT="%d/%m/%y %H:%M "

It depends on which shell you are using. For GNU Bash, changing the HISTTIMEFORMAT variable will help. This nixCraft article explains how to set that variable permanently, but uses an ambiguous date format. For ISO 8601, use:
HISTTIMEFORMAT="%G-%m-%dT%T "
Result:
$ history
[...]
13 2022-11-07T13:32:01 pwd
14 2022-11-07T13:32:05 cd
15 2022-11-07T13:32:10 ls -l

On macOS without editing any rc files:
history -t"%F %T"

Related

Grabbing date from p4 changes command

I am trying to grab the date, CL and user of a list of changelists submitted within a given timeframe.
p4 changes -s submitted //depot/mainline/... #2020/03/09,#2020/03/14
will give me the changes with a date but too much other information. So you can use -F to strip out the information delivered.
p4 -F %change%-%user%-%date% changes -s submitted //depot/mainline/... #2020/03/09,#2020/03/14
But irritatingly -F %date% does not mean "what date was this submitted?" it means "what date is it today?" This is despite the information on the -e flag telling me that %date% is the submitted date.
So any ideas on how to get the submitted date from the -F flag?
Many thanks!
I assume you're on Windows and %date% is getting expanded by the shell so that p4 never sees it:
C:\Perforce\test>echo %date%
Thu 03/19/2020
Escaping the % will prevent that and let p4 see the command you actually wanted to run. In the cmd shell you can escape % as ^%:
C:\Perforce\test>p4 -F ^%date^% changes -m1
2020/03/16

Execute command after every command in bash

I want to print the date after every bash command I run.
This could help me understand how much a command took to execute when I am away from keyboard.
I know I could do
`DATE=`date +%d/%m/%Y\ %H:%M:%S` && echo $DATE`
to get the date but I don't know how or even if it could be possible to run this command after every command I execute on bash.
I would also be interested in running the same command before every command so I could know how long a command took.
Is it possible?
What file should I edit?
For example:
$ wget google.com
15/07/2017 23:40:05
I would be happy, if I could also introduce this following feauture:
$ wget google.com
15/07/2017 23:40:05 15/07/2017 23:40:11
Program run for 00:00:06
where the first date is when I ran the program, second is when program terminated the third is self-explanatonary.
As you understood, I don't want to type every time
$ wget google.com && `DATE=`date +%d/%m/%Y\ %H:%M:%S` && echo $DATE`
To execute a cmd before every command entered, set a trap on DEBUG. Eg.
trap date DEBUG
To execute that command before emitting a prompt, set PROMPT_COMMAND:
PROMPT_COMMAND=date
This does exactly that:
PROMPT_COMMAND+=$'\n'"date +%d/%m/%Y\ %H:%M:%S"
The string in PROMPT_COMMAND gets evaluated after every command. You just need to add the date command to whatever you already had in it. ($'\n' (newline) is a somewhat more robust joiner than ; as two consecutive ; would give you a syntax error)
You can add date/time to your prompt, via PS1 variable. You could use date command, but it's more efficient to use the supported special characters, like \d for date, or \D{strftime-fmt}.
For example:
PS1='\u#\h[\D{%F} \D{%T}]\w\$ '
or, with color:
PS1='\[\033[01;32m\]\u#\h\[\033[00m\][\[\033[02;33m\]\D{%F}\[\033[08m\]T\[\033[00m\]\[\033[02;33m\]\D{%T}\[\033[00m\]]\[\033[01;34m\]\w\[\033[00m\]\$ '
will show:
user#host[2017-07-16 00:01:17]~/somedir$
Note that in the second case (with color) we have a valid ISO8601 timestamp, with a "hidden" date/time separator T in the middle. If you select it with a mouse, T is visible and can be copied. (Also double-click will select the complete timestamp, not only date or time.)
To print timestamp after every command just modify your PS1 prompt and add date to it. The only catch here is that it will tell you time when command ended and new prompt showed. So in case you have your prompt open for long time just hit enter to capture start time before running your command.
PS1="\D{%F %T} \$ "
See this arch wiki page or just google bash prompt customization.
To add time spent executing program just add time before the command
$ time wget google.com
It will give you output like this
real 0m0.177s
user 0m0.156s
sys 0m0.020s
And you can get even more lazy and for commands that you dont't feel like typing time every time you run it, just create alias.
alias wget="time wget"
Because in bash aliases are run before other commands you can do it this way even if it looks like recursion. Then you will call it as you are used to.
And of course, aliases and prompt settings can be put in your .bashrc file, so you don't have to type them every time you open terminal.

Gnu time and formatting output

I wanted to use gnu time to measure running time of some little .c programs. In the man it is written that:
-f FORMAT, --format FORMAT
Use FORMAT as the format string that controls the output of time. See the below more information.
Then in examples we have:
To run the command `ls -Fs' and show just the user, system, and total time:
time -f "%E real,%U user,%S sys" ls -Fs
But when I try to issue this command from example i get:
time -f '%E real,%U user,%S sys' ls -Fs
-f: command not found
real 0m0.134s
user 0m0.084s
sys 0m0.044s
I am wondering where is the problem, where am I making a mistake? I just want to show the user time, that is why I am toying with time output format.
Bash for one has a shell builtin named time. One way to get past it is to type command time - command will ignore the builtins and run the time program from your $PATH. Another way is alias time=/usr/bin/time. On the other hand the bash builtin respects environment variable TIMEFORMAT.
The documentation also mentions env time to use the time command from the system (it uses /usr/bin/env or alike, so it should be independent of the shell).

Proper format for a mysqldump dynamic filename in a cron?

I have a crontab set up that errors out every time I attempt to do it. It works fine in the shell. It's the format I'm using when I attempt to automatically insert the date into the filename of the database backup. Does anyone know the syntax I need to use to get cron to let me insert the date into the filename?
mysqldump -hServer -uUser -pPassword Table | gzip >
/home/directory/backups/table.$(date +"%Y-%m-%d").gz
Thanks in advance!
What about something like this for the "command" part of the crontab :
mysqldump --host=HOST --user=USER --password=PASSWORD DATABASE TABLE | gzip > /tmp/table.`date +"\%Y-\%m-\%d"`.gz
What has changed from OP is the escaping of the date format :
date +"\%Y-\%m-\%d"
(And I used backticks -- but that should do much of a difference)
(Other solution would be to put your original command in a shell-script, and execute this one from the crontab, instead of the command -- would probably be easier to read/write ^^)
The most typical reason for "works in shell but not in cron" is that commands you try to execute are not in PATH.. Reason is that shell invoked from cron aint loading same files as your login shell.
Fix: add absolute path to each command you try to execute.
Second thing i notice in your command. Syntax for running your date command looks like its not very portable. Change that to be in backticks, or run put your whole command to shellscript (also, you can use it to set your path too) and execute that script from cron..
EDIT:
During the writing my original reply my keyboard layout didnt have backticks so check what Pascal wrote.
And example of what you could do with a shellscript:
Copy following to /usr/local/bin/dumptable.sh
#!/bin/sh
/usr/bin/mysqldump --host=HOST --user=USER --password=PASSWORD DATABASE TABLE | /bin/gzip > /tmp/table.`/bin/date +"\%Y-\%m-\%d"`.gz
and then put the the /usr/local/bin/dumptable.sh into cron..

Save in a variable the number of seconds a process took to run

I want to run a process in bash and save in an env variable the number of seconds it took to run.
How would I do such a thing?
Are you wanting to put this code in your script, or do it from the process that starts the script?
For the latter, you can use the "time" reserved word and then parse what it returns to get how much time a script takes.
If you want to do this from within a script you can set the variable SECONDS to zero, and each time thereafter that you reference that variable it will be updated to be the number of elapsed seconds. So, you can put "SECONDS=0" at the very start of your script, and whenever you need the elapsed time it will be in the SECONDS variable.
You can also use the $SECONDS trick on the command line as well, for example:
$ SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"
The time reserved word and the SECONDS variable are both documented in the bash man page.
This works in Bash, and also Zsh:
# Set time format to seconds
TIMEFORMAT=%R
# Time a process
PROC_TIME=$(time (insert command here >/dev/null 2>&1) 2>&1)
echo $PROC_TIME
The first two redirections hide your process's output ">/dev/null 2>&1"
The last redirect is needed because "time" prints the time on stderr
Using GNU time,
\time -p -o time.log $COMMAND
and then read time.log.
(Use either \time or command time, otherwise you'll be using Bash's time built-in, which doesn't support these options.)
This will work even when $COMMAND prints to stderr (which would confuse Oli's answer), and keeps stdout/stderr (which Farzy's answer doesn't).
-o ... tells time to send its output to a file rather than to stderr (as is the default), and -p generates the traditional
real 0.00
user 0.00
sys 0.00
rather than GNU time's default of
0.00user 0.00system 0:00.01elapsed 8%CPU (0avgtext+0avgdata 0maxresident)k
80inputs+0outputs (1major+188minor)pagefaults 0swaps
Using $SECONDS wasn't working for me in a script run by cron (though it worked when I ran it directly; I used cron for the first time today, so there could be some user error too). #Farzy's answer using TIMEFORMAT worked but I didn't want to redirect the output from the timed command. Here's an alternative to $SECONDS if you're in a similar situation:
start=$(date +%s)
your_command
seconds=$(($(date +%s) - $start))
Use the time command. Note that the bash version of time is not the same as /usr/bin/time. So you would have something like:
TIME=`/usr/bin/time --format="%e" your_command_here >/dev/null`
The format just pulls the "real" time value out. You would need to convert that from a string if you wanted to do anything more than display it.
If you just want to export the string, use export.

Resources