Unable to save history from inside a bash script - linux

I'm writing a simple bash script but the commands within the script do not anything. However it works when I copy/paste the commands directly to the command line.
#!/bin/bash
today=$(date +%B-%A-%d-%Y)
expr='clear|ls|cd'
history | grep -v -E $expr > histor$today.txt
history -c
Suggestions?
Another question: is possible to call and execute any command of the command line?
NOTE: I would like to make a script that saves my command history except the commands "clear, ls, cd" and then use crontab to save it periodically.

By default, the history facility is only enabled in interactive shells, not shells running scripts. You can put
set -o history
at the beginning of your script to enable history.
Also, each shell invocation has its own history, it's not shared between shells. So enabling history in the script will not give it access to the history of your interactive shell. So the only history that your script would find are the commands that were executed in the script after set -o history.
What you should do instead is define a function in your .bashrc.
gethist() {
history | grep -v -E 'clear|ls|cd' > $(date +'histor%B-%A-%d-%Y.txt')
}

Related

Does bash shell script leave its command history?

Does bash shell script leave the history of the commands it executed, such as .bash_history?
I'm curious about it.
No, it does not:
https://www.gnu.org/software/bash/manual/html_node/Bash-History-Facilities.html
9.1 Bash History Facilities
When the -o history option to the set builtin is enabled (see The Set Builtin), the shell provides access to the command history, the list of commands previously typed.
To get current settings, use set -o command. In interactive shells (with -i option of bash or in usual bashes from login or terminal) it prints history on. When used in scripts (bash -c 'set -o' or when you did ssh machine bash without tty allocation) it is unset: history off.
https://www.gnu.org/software/bash/manual/html_node/Interactive-Shell-Behavior.html
6.3.3 Interactive Shell Behavior - When the shell is running interactively, it changes its behavior in several ways.
Command history (see Bash History Facilities) and history expansion (see History Interaction) are enabled by default. Bash will save the command history to the file named by $HISTFILE when a shell with history enabled exits.
History can be enabled in script with several commands: https://askubuntu.com/questions/546556/how-can-i-use-history-command-in-a-bash-script / https://unix.stackexchange.com/questions/5684/history-command-inside-bash-script - set HISTFILE and (optionally) HISTTIMEFORMAT, enable with set -o history and then use history command.

Can make shell run interactively along with --command option

I'm using GNU bash that is installed as git bash. On startup I need to change directory, so I'm doing it like this:
"C:\Program Files\Git\bin\sh.exe" --rcfile "./cd.sh"
Where cd.sh just contains cd /d/ command. Everything works fine here. Now I'm trying to get rid of cd.sh file and pass command to the shell as a parameter yet I want it to remain interactive, so I'm doing like this:
"C:\Program Files\Git\bin\sh.exe" -ic "cd /d"
It executes the command (tested with echo command) but then exits. Why doesn't it stay interactive?
From man bash:
An interactive shell is one started without non-option arguments and without the -c option ...
From man dash:
If no args are present and if the standard input of the shell is connected to a terminal (or if the -i flag is set), and the -c option is not present, the shell is considered an interactive shell.

Wrong BASH-Variable return from a bash script

I'd like to check the value of $HISTFILE (or any similar BASH-Variable) by a bash script. On the command console 'echo $HISTFILE' is the way I normally go, but from inside a bash script, which only includes:
#!/bin/bash
echo $HISTFILE
gives an empty line instead of showing $HOME/$USER/.bash_history (or similar return values). My questions are:
What is the reason for doing so (since I never had such trouble using bash scripts) and
how can I check the value of BASH-Variables like $HISTFILE from inside a bash script?
Many thanks in advance. Cheers, M.
HISTFILE is only set in interactive shells; scripts run in non-interactive shells. Compare
$ bash -c 'echo $HISTFILE' # non-interactive, no output
$ bash -ic 'echo $HISTFILE' # interactive, produces output
/home/me/.bash_history
However, forcing the script to run in an interactive shell will also cause your .bashrc file to be sourced, which may or may not be desirable.

History command works in a terminal, but doesn't when written as a bash script

I have a simple one-liner that works perfectly in the terminal:
history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head
What it does: Gives out the 10 most frequently used commands by the user recently. (Don't ask me why I would want to achieve such a thing)
I fire up an editor and type the same with a #!/bin/bash in the beginning:
#!/bin/bash
history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head
And say I save it as script.sh. Then when I go to the same terminal, type bash script.sh and hit Enter, nothing happens.
What I have tried so far: Googling. Many people have similar pains but they got resolved by a sudo su or adding/removing spaces. None of this worked for me. Any idea where I might be going wrong?
Edit:
I would want to do this from the terminal itself. The system on which this script would run may or may not provide permissions to change files in the home folder.
Another question as suggested by BryceAtNetwork23, what is so special about the history command that prevents us from executing it?
Looking at your history only makes sense in an interactive shell. Make that command a function instead of a standalone script. In your ~/.bashrc, put
popular_history() {
history | sort -k2 | uniq -c --skip-fields=1 | sort -r -g | head
}
To use history from a non-interactive shell, you need to enable it; it is only on by default for interactive shells. You can add the following line to the shell script:
set -o history
It still appears that only interactive shells will read the default history file by, well, default, so you'll need to populate the history list explicitly with the next line:
history -r ~/.bash_history
(Read the bash man page for more information on using a file other than the default .bash_history.)
History command is disabled by default on bash script, that's why even
history command won't work in .sh file. for its redirection. Kindly
redirect bash_history file inside the .sh file.
History mechanism can be enabled also by mentioning history file and change run-time parameters as mentioned below
#!/bin/bash
HISTFILE=~/.bash_history
set -o history
Note: mentioned above two lines on the top of the script file. Now history command will work in history.

Commands available in bash -i can't access in bash -l

I don't know how to describe it. It just happens when i use vim and set shell=bash -l. Then i found that a command called mm which can execute in terminal can't execute in vim .
And i also found that when i write this command in run.sh and execute this script. It still report command not found. I think there must be something wrong with my $HOME/.bash* files and $HOME/.profile. And i am sure that .profile are almost the same with .bashrc.
From $ man bash:
When bash is invoked as an interactive login shell, or as a
non-interactive shell with the --login option, it first reads
and executes commands from the file /etc/profile, if that file exists.
After reading that file, it looks for ~/.bash_profile,
~/.bash_login, and ~/.profile, in that order, and reads and
executes commands from the first one that exists and is readable.
and
When an interactive shell that is not a login shell is started, bash
reads and executes commands from ~/.bashrc, if that file exists.
So:
shell | files loaded
--------+-----------------
bash -l | /etc/profile
| ~/.bash_profile
| ~/.bash_login
| ~/.profile
--------+-----------------
bash -i | ~/.bashrc

Resources