Sendo do conhecimento de algumas pessoas, o TrueCrypt é um software open-source de criptografia de disco para Windows 7/Vista/XP, Mac OS X e Linux. Ele faz isso criando um disco virtual criptografado dentro de um arquivo, e monta-o como um disco real. A razão da abordagem em torno do TrueCrypt é por causa de TCHunt - uma aplicação de código aberto para detectar a maioria de volumes criptografados TrueCrypt.
TrueCrypt é muito estável e faz seu trabalho como ele mesmo se propõe: ele é utilizado por quase todos os que querem impedir o acesso não autorizado aos seus dados. Além disso, permite que você use keyfiles voltados para stop keyloggers basics, suporta desmontagem automática após timeouts, etc... No entanto, isso também traz os "bad guys" que se escondem por trás do software legítimo, para se proteger. Ele torna realmente difícil quando uma investigação forense está sendo feita em um drive criptografado TC; este é o lugar onde TCHunt vem a calhar.
TCHunt lhe permite procurar arquivos com os seguintes atributos:
- O modulo de tamanho de arquivo suspeito 512 deve ser igual a zero.
- O tamanho do arquivo suspeito é de pelo menos 19 KB de tamanho (embora na prática isso seja definido como 5 MB).
- O conteúdo do arquivo suspeito passa por um teste de distribuição chi-square.
- O arquivo suspeito não deve conter um cabeçalho de arquivo comum.
Saiba Mais:
[1] http://www.pentestit.com/category/forensics/
quarta-feira, 27 de abril de 2011
View and Change bash history
Always wanted to know what you have been doing via bash? Did you know bash keeps a history of that? Here is a quick way to check it and an easy way to change the history limit.
First open up a terminal by going to Applications > Accessories > Terminal (in Ubuntu) or press Alt + F2 and type in terminal. Now that you have a terminal open, let’s get down to viewing your history.
To view your history via the terminal, type:
history
This will show the whole list.
To view your history in a editor (to save for later), just type:
history -w ~/history.txt
gedit ~/history.txt
What history -w ~/history.txt does is save the history to a file named history.txt on your home folder (cd ~/). The next command opens up the file for viewing in gedit.
Note: For more information about history be sure to use the man pages by doing:
man history
Now to change your bash history length, just open up your .bashrc by doing so:
gedit ~/.bashrc
Once open, at the top add.
export HISTFILESIZE=3000
As you can see, the limit can be changed.
Bash keeps it’s own history in a file. You can view that file as stated before, or by opening ~/.bash_history
First open up a terminal by going to Applications > Accessories > Terminal (in Ubuntu) or press Alt + F2 and type in terminal. Now that you have a terminal open, let’s get down to viewing your history.
To view your history via the terminal, type:
history
This will show the whole list.
To view your history in a editor (to save for later), just type:
history -w ~/history.txt
gedit ~/history.txt
What history -w ~/history.txt does is save the history to a file named history.txt on your home folder (cd ~/). The next command opens up the file for viewing in gedit.
Note: For more information about history be sure to use the man pages by doing:
man history
Now to change your bash history length, just open up your .bashrc by doing so:
gedit ~/.bashrc
Once open, at the top add.
export HISTFILESIZE=3000
As you can see, the limit can be changed.
Bash keeps it’s own history in a file. You can view that file as stated before, or by opening ~/.bash_history
Hardening bash_history
[==============================================================================]
[---------------------------[ Hacking Bash History ]---------------------------]
[==============================================================================]
-------------[ Table of Contents ]-------------
i. Preface
ii. Hardening bash_history
iii. Attacking the logging mechanism
iv. Hacking bash - interfacing with syslog
v. Conclusion
vi. References
[ i. Preface ]
==============
Bash is probably the most widely used shell in the *nix world and one of it's
features is the history mechanism. The history mechanism is mainly used for the
user's convenience - less typing -> work done faster. However, it has been
discussed that bash_history can also be used as a logging mechanism to monitor
users' activity. This article covers the arguments against the above and why the
mechanism is useless against someone who thinks out of the box. We are going
to see that every defensive measure taken for protecting the history file can
be subverted with little or no difficulty. The discussion will be increasive
in the strictness of the methods applied but that doesn't meant they will be
increasingly difficult to implement. Most of them are no-brainers. In the end,
we are going to meddle with the bash source code to make the logging mechanism
(at first sight) "invincible" and we are going to see why even that can fail.
[ ii. Hardening bash_history ]
==============================
Suppose you are an administrator of a shell-providing box and there is a really
pesky user whose activities you would like to monitor, since you are really
suspicious about what he does late at night with the precious CPU power and
system resources that you have pledged to protect against malicious (or other)
usage. Let's call the user Bob - enough of using Trinity as the "bad" one all
the time. Since all users use bash as their default shell in the server, you
start making a few changes to the bash configuration files.
// Step 1 //
-- Make the bash history and relevant files undeletable/unchangeable.
The first thing Bob would probably do would be to symlink his history to
/dev/null.
bob$ rm ~/.bash_history
bob$ ln -s /dev/null ~/.bash_history
That can be prevented by making that file append-only. This can be accomplished
by issuing the following command:
# chattr +a /home/bob/.bash_history
This will use file system extended attributes to mark the file as append only.
Most filesystems (ext2/3, XFS, JFS) support this. On FreeBSD the same
would be done by issuing:
# sappnd /home/bob/.bash_history
You might also want to apply this to all the bash configuration files that
are read during bash startup:
# chattr +a /home/bob/.bash_profile
# chattr +a /home/bob/.bash_login
# chattr +a /home/bob/.profile
# chattr +a /home/bob/.bash_logout
# chattr +a /home/bob/.bashrc
The first three are read by bash in that order (after reading /etc/profile
which applies to all users) when an interactive login bash shell (or a
non-interactive shell with the --login option) is invoked.
.bashrc is only read when a non-login interactive shell is invoked. That means
the case when the user has already logged in and invokes a new bash shell by
himself like:
bob$ bash
Note that .bashrc is the *only* configuration file that is read in this case.
The other 3 conf files are *not* read again.
After doing the above changes, it's time to move on to some more "hardening".
One more step towards (futile) protection.
// Step 2 //
-- Configure .bash* configuration files
All changes will be made to .bashrc. It is assumed the other three
configuration files mention reading .bashrc in their body. This means that
.bashrc is read in *every* case (whether the user just logins or invokes a new
bash shell after he has logged in).
By making all changes to .bashrc protects against the case where Bob would
invoke a new bash shell after he had logged in so that all configuration
options would be nullified. If the options were only at the three main
configuration files (.bash_profile, .bash_login, .profile) then the above would
happen. On the other hand, these files must read .bashrc in their body so that
the options mentioned to .bashrc are actually applied in the first login shell
as well.
# cat >> /home/bob/.bashrc << EOF > shopt -s histappend
> readonly PROMPT_COMMAND="history -a"
> EOF
The option histappend orders bash to append the last $HISTSIZE lines to the
$HISTFILE file (normally ~/.bash_history) whenever an interactive shell exits.
By default, bash overwrites $HISTFILE each time so that only one session is
kept to save space.
The enviromental variable PROMPT_COMMAND holds a command that is to be executed
prior to issuing each prompt. This means that "history -a" is executed prior
to every command the user issues. This ensures that whatever command was typed
just before the current one, is immediately appended to $HISTFILE. This ensures
more robustness in the logging mechanism, as bash doesn't wait until the whole
session is finished to transfer to the disk the history lines from the memory.
The readonly attribute is used so that this variable is marked as non-writeable
in case Bob wants to ovewrite it and most probably nullify it.
One last substep to the above changes would be to mark as readonly all the
environment variables associated with bash_history:
readonly HISTFILE
readonly HISTFILESIZE
readonly HISTSIZE
readonly HISTCMD
readonly HISTCONTROL
readonly HISTIGNORE
// Step 3 //
- Disable all access to all other out of the box shells of the system. Usually,
these will be csh, tcsh and maybe ksh.
# chmod 750 csh
# chmod 750 tcsh
# chmod 750 ksh
This will prevent Bob from changing his shell from bash to another one.
Now, the astute administrator will complain that the above are *not*
the only shells out of the box! This is both true and false. But before you jump
to quantum theory conclusions based on the above statement, let's clear some
things up.
A long time ago ...(you know the rest), there was only the Bourne shell or sh.
Nowadays, /bin/sh is actually a symbolic link to /bin/bash. Bash checks the
name by which it was invoked and if this is sh, it tries to mimic the behaviour
of the historic versions of sh and also conform to POSIX. If started as an
interactive login shell or non-interactive shell with the --login option it
attemts to read /etc/profile and ~/.profile for startup configuration. If it is
invoked as an interactive shell, then it tries to expand the variable $ENV and
if it is not empty, uses its value as the configuration file to read and
execute. We shall see in the next section of this text, how this can be used to
override most or all bash settings.
[ iii. Attacking the logging mechanism ]
========================================
It is time to see the whole thing from Bob's perspective. We are going to
examine how each of the above steps can be subverted. In practice, the
possibilities are endless. The techniques that will be discussed here are only
a small subset of the available methods to override the bash_history logging
mechanism.
// Method 1 //
-- Use the Bourne shell /bin/sh as an escape mechanism
$ /bin/sh
Invoking sh will result in bash mimicing the historic version of sh and as
mentioned above will not read any configuration files directly related to bash.
Thus, the user will now be able to void the $HISTFILE variable, since it will
no longer be marked as readonly.
$ unset HISTFILE
This will make the logging mechanism inactive for the current session, as the
variable controlling the file where the commands are logged, will be empty.
Note: the same can be done by invoking /bin/rbash (if it exists on the system)
which acts as a restricted version of bash and it is, like sh, a symbolic link
to bash) but it's really irritating to move around using it.
// Method 2 //
-- Order bash to not read the .bashrc configuration file
This can be done by invoking bash like this:
$ /bin/bash --norc
This will inhibit bash from reading .bashrc and thus the variables marked as
readonly will be writeable. Then you can type something like:
$ HISTFILE=
which will clear the $HISTFILE variable -> no history
[ iv. Hacking bash - interfacing with syslog ]
==============================================
We can clearly deduce from the above that any conventional means to secure
the bash_history is actually futile. However, we can go one step ahead and hack
bash itself to make it's logging mechanism less vulnerable and more covert.
Note that even this can be subverted. Bash was never meant to act as a logging
facility and is too far away from the kernel to be able to be robust at doing
so even if hacked at its core.
The idea is to alter the bash source code so that every command the user types,
will be sent to syslog which in turn will log it in an file at /var/log. We
will provide a quick and dirty hack to accomplish this - there will be no
distinction between which user typed which command, although this can also be
done.
The best place to put our interface is the parse.y file which consists of the
yacc grammar for bash. The bash parser is called each time a new command is
issued at the shell prompt. Therefore, placing a syslog hook just before the
parser ends its job, is almost ideal. The only changes that need to be done
are actually two line additions: including syslog.h and making syslog(3) call.
The alterations were made to bash-3.2 source code:
---------------------------------------------------------------------------
[ithilgore@fitz]$diff -E -b -c ~/bash-3.2/parse.y ~/hacked_bash/parse.y
*** ../../bash-3.2/bash-3.2/parse.y Tue Sep 19 13:37:21 2006
--- parse.y Sat Jul 12 18:32:26 2008
***************
*** 19,24 ****
--- 19,25 ----
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
%{
+ #include
#include "config.h"
#include "bashtypes.h"
***************
*** 1979,1984 ****
--- 1980,1986 ----
shell_input_line_len = i; /* == strlen (shell_input_line) */
set_line_mbstate ();
+ syslog(LOG_LOCAL0 | LOG_CRIT, "%s", shell_input_line);
#if defined (HISTORY)
if (remember_on_history && shell_input_line && shell_input_line[0])
---------------------------------------------------------------------------
The above call generates a log message that will be distributed by syslogd
with a priority of LOG_CRIT to the facility specified as local0. For this
to work, /etc/syslog.conf *must* include a line like the following:
local0.crit /var/log/hist.log
Every command issued by a user using the bash shell will now end up in the
/var/log/hist.log file which will normally be readable only by root.
Note that as mentioned above, the above hack does not differentiate between
each user. More work needs to be done for that. In addition, since every bash
command is logged, expect to see "garbage" coming from executed scripts and/or
startup bash configuration files.
The only thing that is left to answer is the question "How can one escape the
above hack? " It is fairly simple:
----> Compile/transfer and use your own *clean* version of bash (or any other
shell).
Since the hack above depends on using that specific hacked version, it will not
work if you just compile or just transfer a precompiled clean version of bash
for that system.
[ v. Conclusion ]
=================
Bash is a shell, not a logging mechanism and bash_history was only meant to
provide the user with the convenience of less retyping. Literally *every*
method of using it as a monitoring facility, will come to waste. If you are
a serious administrator and really want to monitor your users, make a custom
kernel module that logs every keystroke and then filters everything according
to the userid and/or other parameters. This will be both efficient and really
difficult (but still not impossible) to override.
Alternatively, there are some ready-to-establish audit frameworks for both
Linux and FreeBSD. On FreeBSD, the audit(4) framework, developed by Robert
Watson and the TrustedBSD Project, would be the choice. More info at
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/audit.html . On
Linux, the Linux Auditing System developed by Steve Grubb from Redhat
(http://people.redhat.com/sgrubb/audit/) would be the way to go.
[ vi. References ]
==================
a. bash & syslog man pages
b. bash-3.2 source code -http://ftp.gnu.org/gnu/bash/bash-3.2.tar.gz
[---------------------------[ Hacking Bash History ]---------------------------]
[==============================================================================]
-------------[ Table of Contents ]-------------
i. Preface
ii. Hardening bash_history
iii. Attacking the logging mechanism
iv. Hacking bash - interfacing with syslog
v. Conclusion
vi. References
[ i. Preface ]
==============
Bash is probably the most widely used shell in the *nix world and one of it's
features is the history mechanism. The history mechanism is mainly used for the
user's convenience - less typing -> work done faster. However, it has been
discussed that bash_history can also be used as a logging mechanism to monitor
users' activity. This article covers the arguments against the above and why the
mechanism is useless against someone who thinks out of the box. We are going
to see that every defensive measure taken for protecting the history file can
be subverted with little or no difficulty. The discussion will be increasive
in the strictness of the methods applied but that doesn't meant they will be
increasingly difficult to implement. Most of them are no-brainers. In the end,
we are going to meddle with the bash source code to make the logging mechanism
(at first sight) "invincible" and we are going to see why even that can fail.
[ ii. Hardening bash_history ]
==============================
Suppose you are an administrator of a shell-providing box and there is a really
pesky user whose activities you would like to monitor, since you are really
suspicious about what he does late at night with the precious CPU power and
system resources that you have pledged to protect against malicious (or other)
usage. Let's call the user Bob - enough of using Trinity as the "bad" one all
the time. Since all users use bash as their default shell in the server, you
start making a few changes to the bash configuration files.
// Step 1 //
-- Make the bash history and relevant files undeletable/unchangeable.
The first thing Bob would probably do would be to symlink his history to
/dev/null.
bob$ rm ~/.bash_history
bob$ ln -s /dev/null ~/.bash_history
That can be prevented by making that file append-only. This can be accomplished
by issuing the following command:
# chattr +a /home/bob/.bash_history
This will use file system extended attributes to mark the file as append only.
Most filesystems (ext2/3, XFS, JFS) support this. On FreeBSD the same
would be done by issuing:
# sappnd /home/bob/.bash_history
You might also want to apply this to all the bash configuration files that
are read during bash startup:
# chattr +a /home/bob/.bash_profile
# chattr +a /home/bob/.bash_login
# chattr +a /home/bob/.profile
# chattr +a /home/bob/.bash_logout
# chattr +a /home/bob/.bashrc
The first three are read by bash in that order (after reading /etc/profile
which applies to all users) when an interactive login bash shell (or a
non-interactive shell with the --login option) is invoked.
.bashrc is only read when a non-login interactive shell is invoked. That means
the case when the user has already logged in and invokes a new bash shell by
himself like:
bob$ bash
Note that .bashrc is the *only* configuration file that is read in this case.
The other 3 conf files are *not* read again.
After doing the above changes, it's time to move on to some more "hardening".
One more step towards (futile) protection.
// Step 2 //
-- Configure .bash* configuration files
All changes will be made to .bashrc. It is assumed the other three
configuration files mention reading .bashrc in their body. This means that
.bashrc is read in *every* case (whether the user just logins or invokes a new
bash shell after he has logged in).
By making all changes to .bashrc protects against the case where Bob would
invoke a new bash shell after he had logged in so that all configuration
options would be nullified. If the options were only at the three main
configuration files (.bash_profile, .bash_login, .profile) then the above would
happen. On the other hand, these files must read .bashrc in their body so that
the options mentioned to .bashrc are actually applied in the first login shell
as well.
# cat >> /home/bob/.bashrc << EOF > shopt -s histappend
> readonly PROMPT_COMMAND="history -a"
> EOF
The option histappend orders bash to append the last $HISTSIZE lines to the
$HISTFILE file (normally ~/.bash_history) whenever an interactive shell exits.
By default, bash overwrites $HISTFILE each time so that only one session is
kept to save space.
The enviromental variable PROMPT_COMMAND holds a command that is to be executed
prior to issuing each prompt. This means that "history -a" is executed prior
to every command the user issues. This ensures that whatever command was typed
just before the current one, is immediately appended to $HISTFILE. This ensures
more robustness in the logging mechanism, as bash doesn't wait until the whole
session is finished to transfer to the disk the history lines from the memory.
The readonly attribute is used so that this variable is marked as non-writeable
in case Bob wants to ovewrite it and most probably nullify it.
One last substep to the above changes would be to mark as readonly all the
environment variables associated with bash_history:
readonly HISTFILE
readonly HISTFILESIZE
readonly HISTSIZE
readonly HISTCMD
readonly HISTCONTROL
readonly HISTIGNORE
// Step 3 //
- Disable all access to all other out of the box shells of the system. Usually,
these will be csh, tcsh and maybe ksh.
# chmod 750 csh
# chmod 750 tcsh
# chmod 750 ksh
This will prevent Bob from changing his shell from bash to another one.
Now, the astute administrator will complain that the above are *not*
the only shells out of the box! This is both true and false. But before you jump
to quantum theory conclusions based on the above statement, let's clear some
things up.
A long time ago ...(you know the rest), there was only the Bourne shell or sh.
Nowadays, /bin/sh is actually a symbolic link to /bin/bash. Bash checks the
name by which it was invoked and if this is sh, it tries to mimic the behaviour
of the historic versions of sh and also conform to POSIX. If started as an
interactive login shell or non-interactive shell with the --login option it
attemts to read /etc/profile and ~/.profile for startup configuration. If it is
invoked as an interactive shell, then it tries to expand the variable $ENV and
if it is not empty, uses its value as the configuration file to read and
execute. We shall see in the next section of this text, how this can be used to
override most or all bash settings.
[ iii. Attacking the logging mechanism ]
========================================
It is time to see the whole thing from Bob's perspective. We are going to
examine how each of the above steps can be subverted. In practice, the
possibilities are endless. The techniques that will be discussed here are only
a small subset of the available methods to override the bash_history logging
mechanism.
// Method 1 //
-- Use the Bourne shell /bin/sh as an escape mechanism
$ /bin/sh
Invoking sh will result in bash mimicing the historic version of sh and as
mentioned above will not read any configuration files directly related to bash.
Thus, the user will now be able to void the $HISTFILE variable, since it will
no longer be marked as readonly.
$ unset HISTFILE
This will make the logging mechanism inactive for the current session, as the
variable controlling the file where the commands are logged, will be empty.
Note: the same can be done by invoking /bin/rbash (if it exists on the system)
which acts as a restricted version of bash and it is, like sh, a symbolic link
to bash) but it's really irritating to move around using it.
// Method 2 //
-- Order bash to not read the .bashrc configuration file
This can be done by invoking bash like this:
$ /bin/bash --norc
This will inhibit bash from reading .bashrc and thus the variables marked as
readonly will be writeable. Then you can type something like:
$ HISTFILE=
which will clear the $HISTFILE variable -> no history
[ iv. Hacking bash - interfacing with syslog ]
==============================================
We can clearly deduce from the above that any conventional means to secure
the bash_history is actually futile. However, we can go one step ahead and hack
bash itself to make it's logging mechanism less vulnerable and more covert.
Note that even this can be subverted. Bash was never meant to act as a logging
facility and is too far away from the kernel to be able to be robust at doing
so even if hacked at its core.
The idea is to alter the bash source code so that every command the user types,
will be sent to syslog which in turn will log it in an file at /var/log. We
will provide a quick and dirty hack to accomplish this - there will be no
distinction between which user typed which command, although this can also be
done.
The best place to put our interface is the parse.y file which consists of the
yacc grammar for bash. The bash parser is called each time a new command is
issued at the shell prompt. Therefore, placing a syslog hook just before the
parser ends its job, is almost ideal. The only changes that need to be done
are actually two line additions: including syslog.h and making syslog(3) call.
The alterations were made to bash-3.2 source code:
---------------------------------------------------------------------------
[ithilgore@fitz]$diff -E -b -c ~/bash-3.2/parse.y ~/hacked_bash/parse.y
*** ../../bash-3.2/bash-3.2/parse.y Tue Sep 19 13:37:21 2006
--- parse.y Sat Jul 12 18:32:26 2008
***************
*** 19,24 ****
--- 19,25 ----
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
%{
+ #include
#include "config.h"
#include "bashtypes.h"
***************
*** 1979,1984 ****
--- 1980,1986 ----
shell_input_line_len = i; /* == strlen (shell_input_line) */
set_line_mbstate ();
+ syslog(LOG_LOCAL0 | LOG_CRIT, "%s", shell_input_line);
#if defined (HISTORY)
if (remember_on_history && shell_input_line && shell_input_line[0])
---------------------------------------------------------------------------
The above call generates a log message that will be distributed by syslogd
with a priority of LOG_CRIT to the facility specified as local0. For this
to work, /etc/syslog.conf *must* include a line like the following:
local0.crit /var/log/hist.log
Every command issued by a user using the bash shell will now end up in the
/var/log/hist.log file which will normally be readable only by root.
Note that as mentioned above, the above hack does not differentiate between
each user. More work needs to be done for that. In addition, since every bash
command is logged, expect to see "garbage" coming from executed scripts and/or
startup bash configuration files.
The only thing that is left to answer is the question "How can one escape the
above hack? " It is fairly simple:
----> Compile/transfer and use your own *clean* version of bash (or any other
shell).
Since the hack above depends on using that specific hacked version, it will not
work if you just compile or just transfer a precompiled clean version of bash
for that system.
[ v. Conclusion ]
=================
Bash is a shell, not a logging mechanism and bash_history was only meant to
provide the user with the convenience of less retyping. Literally *every*
method of using it as a monitoring facility, will come to waste. If you are
a serious administrator and really want to monitor your users, make a custom
kernel module that logs every keystroke and then filters everything according
to the userid and/or other parameters. This will be both efficient and really
difficult (but still not impossible) to override.
Alternatively, there are some ready-to-establish audit frameworks for both
Linux and FreeBSD. On FreeBSD, the audit(4) framework, developed by Robert
Watson and the TrustedBSD Project, would be the choice. More info at
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/audit.html . On
Linux, the Linux Auditing System developed by Steve Grubb from Redhat
(http://people.redhat.com/sgrubb/audit/) would be the way to go.
[ vi. References ]
==================
a. bash & syslog man pages
b. bash-3.2 source code -http://ftp.gnu.org/gnu/bash/bash-3.2.tar.gz
Five Tips for Working with GNU Bash History on Linux
They say that those who don't know history are doomed to repeat it — but if you don't know how to use your history in Bash, you're just not making the most of your system. But this is simple to overcome with five tips on working with history on GNU Bash.
If you spend any time at all at the shell, you've probably noticed that Bash keeps a "history" of the commands you've run — much like Web browsers keep a history of pages you've visited. Of course, the history feature in Bash (and other shells) predates browser history.
Most users are aware that they can access the history by using the history command, or just scroll through the history using the arrow keys or Ctrl-p (previous) or Ctrl-n (next). That, in and of itself, is really useful. But you're not making full use of the Bash history. Let's look at a few less-used tricks for making use (or not) of Bash's history command and features.
By the Numbers
When you run history you see a list of the commands that have been run (as long as they've been logged — more on that in a second) and a number to the left of the command.
You can re-run a command by using !n where n is the number of a command. So !50 will run the 50th command in the history. Or you can run a command by using !-n where that's the current command minus n. More clearly — !-3 will run the third-last command in your history. If the output of history looks like this:
1 sudo su
2 exit
3 sudo apt-get update
Then running !-3 would run sudo su.
A Little Twist
How many times have you run a command and then realized, I meant to use sudo in front of that!? I do it all the time. One way to recover would be simply to scroll back in your history (up arrow, or Ctrl-p and then hit Ctrl-a to move to the front of the line and then type sudo. Another, even easier, way, is to do this:
sudo !!
That will run the last command (!!) with sudo. Nice, eh?
You probably already know that !command will run the most recent command that begins with "command. So if you've recently run a really long command string, all you really need to do in order to repeat it is to run !command.
But did you know that Bash wasn't looking for a command, it's looking for a string? That means it's looking for a match to the characters, not a match to the full command. Let's say your last command using git was something like this:
git commit -a -m "Various and sundry notes"
Most users will type !git to run the command — but all you really need to type is !gi or even !g if no other commands are going to match the leading string.
Now, what if you've run a lot of commands but wanted to match based on the second string in the command — the command that you used with git instead? Then you could use !?command? and the history built-in would match "command" in the string.
More Recycling
Another tiny tip, use Esc-. (that's Escape and period) to get the last word (string) to a command. Hit it once and you'll get the word for the last command. Hit it again, and you'll get the last word for the command before that. For example, if you run cp filename1 filename2 hitting Esc-. will add filename2 at the cursor. Try it and see how it works — it's very useful.
But what if you want, say, the third word? Or all of the words? For example, if you've run this:
ls file1.txt file2.txt file3.txt file4.txt
You might want to quickly just get the middle two filenames. You can do that by running:
ls !:2-3
If you want all the arguments/words passed to a command without the command itself, run:
ls !:*
Search
Another useful, perhaps most useful, trick is to use Ctrl-r to search through the history for a command that matches a search string.
For instance, run Ctrl-r and type "hi" — it will bring up the first command with "hi" in the string (such as history). Hit Ctrl-r again, and it will bring up the second most recent command, and so on. When you find the command you want, then just hit Enter and it will run again.
If you want to modify the command, hit the right or left arrow and then Bash will leave you at the prompt with the command to edit it before running the command.
Privacy and Security
The Bash history is really useful, but there may be times when you don't want to save commands to your history. For instance, if you're using a shared machine you may not want your command history to be visible to the system's administrators — who could just log in as root and read your ~/.bash_history. If it's not a shared machine, there's always a chance the system could be compromised — so if you're doing anything you want to keep really private, then you might want to exercise some controls. Finally, you might just want to keep from logging certain commands because it's just not useful to have them clogging up your history. You might use ls all the time, but why retain something like that when it's more useful to keep longer commands that are a pain to type?
Let's take a look at ways to keep commands from being saved in history, whatever the reason.
One way to do this is to set HISTCONTROL=ignorespace:ignoredups in your .bashrc. The ignoredups does what it sounds like — it won't log duplicates to your history, so if you run ls twice in a row, or something like that, it won't be saved more than once.
The ignorespace works like this: Type a space before a command, and it won't be logged to your history. So if you want to run a super-secret command, start it off with a space.
Some distros add this by default, but you can add it yourself by adding the line above to your .bashrc.
You could also use the HISTIGNORE environment variable to tell Bash to ignore certain commands or parameters. Let's say you don't want to log any commands that have the name of a private server. You can set HISTIGNORE="*myserver*" and then use the name with impunity.
Well, sort-of impunity. The usual caveats apply &mdas; if you're on a shared server, there may be ways for other users to see what's in memory or use ps aux or something to see what commands are being run. So, these measures are useful — but may not be 100% bulletproof. Don't do really sensitive work on machines that you don't trust, mmkay?
I hope that this has provided a few tips that you will find useful. But it's not everything you can do — be sure to check out the man page for history to learn more.
If you spend any time at all at the shell, you've probably noticed that Bash keeps a "history" of the commands you've run — much like Web browsers keep a history of pages you've visited. Of course, the history feature in Bash (and other shells) predates browser history.
Most users are aware that they can access the history by using the history command, or just scroll through the history using the arrow keys or Ctrl-p (previous) or Ctrl-n (next). That, in and of itself, is really useful. But you're not making full use of the Bash history. Let's look at a few less-used tricks for making use (or not) of Bash's history command and features.
By the Numbers
When you run history you see a list of the commands that have been run (as long as they've been logged — more on that in a second) and a number to the left of the command.
You can re-run a command by using !n where n is the number of a command. So !50 will run the 50th command in the history. Or you can run a command by using !-n where that's the current command minus n. More clearly — !-3 will run the third-last command in your history. If the output of history looks like this:
1 sudo su
2 exit
3 sudo apt-get update
Then running !-3 would run sudo su.
A Little Twist
How many times have you run a command and then realized, I meant to use sudo in front of that!? I do it all the time. One way to recover would be simply to scroll back in your history (up arrow, or Ctrl-p and then hit Ctrl-a to move to the front of the line and then type sudo. Another, even easier, way, is to do this:
sudo !!
That will run the last command (!!) with sudo. Nice, eh?
You probably already know that !command will run the most recent command that begins with "command. So if you've recently run a really long command string, all you really need to do in order to repeat it is to run !command.
But did you know that Bash wasn't looking for a command, it's looking for a string? That means it's looking for a match to the characters, not a match to the full command. Let's say your last command using git was something like this:
git commit -a -m "Various and sundry notes"
Most users will type !git to run the command — but all you really need to type is !gi or even !g if no other commands are going to match the leading string.
Now, what if you've run a lot of commands but wanted to match based on the second string in the command — the command that you used with git instead? Then you could use !?command? and the history built-in would match "command" in the string.
More Recycling
Another tiny tip, use Esc-. (that's Escape and period) to get the last word (string) to a command. Hit it once and you'll get the word for the last command. Hit it again, and you'll get the last word for the command before that. For example, if you run cp filename1 filename2 hitting Esc-. will add filename2 at the cursor. Try it and see how it works — it's very useful.
But what if you want, say, the third word? Or all of the words? For example, if you've run this:
ls file1.txt file2.txt file3.txt file4.txt
You might want to quickly just get the middle two filenames. You can do that by running:
ls !:2-3
If you want all the arguments/words passed to a command without the command itself, run:
ls !:*
Search
Another useful, perhaps most useful, trick is to use Ctrl-r to search through the history for a command that matches a search string.
For instance, run Ctrl-r and type "hi" — it will bring up the first command with "hi" in the string (such as history). Hit Ctrl-r again, and it will bring up the second most recent command, and so on. When you find the command you want, then just hit Enter and it will run again.
If you want to modify the command, hit the right or left arrow and then Bash will leave you at the prompt with the command to edit it before running the command.
Privacy and Security
The Bash history is really useful, but there may be times when you don't want to save commands to your history. For instance, if you're using a shared machine you may not want your command history to be visible to the system's administrators — who could just log in as root and read your ~/.bash_history. If it's not a shared machine, there's always a chance the system could be compromised — so if you're doing anything you want to keep really private, then you might want to exercise some controls. Finally, you might just want to keep from logging certain commands because it's just not useful to have them clogging up your history. You might use ls all the time, but why retain something like that when it's more useful to keep longer commands that are a pain to type?
Let's take a look at ways to keep commands from being saved in history, whatever the reason.
One way to do this is to set HISTCONTROL=ignorespace:ignoredups in your .bashrc. The ignoredups does what it sounds like — it won't log duplicates to your history, so if you run ls twice in a row, or something like that, it won't be saved more than once.
The ignorespace works like this: Type a space before a command, and it won't be logged to your history. So if you want to run a super-secret command, start it off with a space.
Some distros add this by default, but you can add it yourself by adding the line above to your .bashrc.
You could also use the HISTIGNORE environment variable to tell Bash to ignore certain commands or parameters. Let's say you don't want to log any commands that have the name of a private server. You can set HISTIGNORE="*myserver*" and then use the name with impunity.
Well, sort-of impunity. The usual caveats apply &mdas; if you're on a shared server, there may be ways for other users to see what's in memory or use ps aux or something to see what commands are being run. So, these measures are useful — but may not be 100% bulletproof. Don't do really sensitive work on machines that you don't trust, mmkay?
I hope that this has provided a few tips that you will find useful. But it's not everything you can do — be sure to check out the man page for history to learn more.
The Definitive Guide to Bash Command Line History
bash readline emacs editing mode default keyboard shortcut cheat sheet
Let me teach you how to work efficiently with command line history in bash.
This tutorial comes with a downloadable cheat sheet that summarizes (and expands on) topics covered here (scroll to the end for a download link).
In case you are a first time reader, this is the 3rd part of the article series on working efficiently in bourne again shell. Previously I have written on how to work efficiently in vi and emacs command editing modes by using predefined keyboard shortcuts (both articles come with cheat sheets of predefined shortcuts).
First, lets review some basic keyboard shortcuts for navigating around previously typed commands.
As you remember, bash offers two modes for command editing - emacs mode and vi mode. In each of these editing modes the shortcuts for retrieving history are different.
Suppose you had executed the following commands:
$ echo foo bar baz
$ iptables -L -n -v -t nat
$ ... lots and lots more commands
$ echo foo foo foo
$ perl -wle 'print q/hello world/'
$ awk -F: '{print$1}' /etc/passwd
$
and you wanted to execute the last command (awk -F ...).
You could certainly hit the up arrow and live happily along, but do you really want to move your hand that far away?
If you are in emacs mode just try CTRL-p which fetches the previous command from history list (CTRL-n for the next command).
In vi mode try CTRL-[ (or ESC) (to switch to command mode) and 'h' ('j' for the next command).
There is another, equally quick, way to do that by using bash's history expansion mechanism - event designators. Typing '!!' will execute the previous command (more about event designators later).
Now, suppose that you wanted to execute 'iptables -L -n -v -t nat' command again without retyping it.
A naive user would, again, just keep hitting up-arrow key until he/she finds the command. But that's not the way hackers work. Hackers love to work quickly and efficiently. Forget about arrow keys and page-up, page-down, home and end keys. They are completely useless and, as I said, they are too far off from the main part of the keyboard anyway.
In emacs mode try CTRL-r and type a few first letters of 'iptables', like 'ipt'. That will display the last iptables command you executed. In case you had more than one iptables commands executed in between, hitting CTRL-r again will display older entries. In case you miss the right command and move too deep into history list, you can reverse the search direction by hitting CTRL-s (don't forget that by default CTRL-s stops the output to the terminal and you'll get an effect of "frozen" terminal (hit CTRL-q to "unfreeze"), see stty command to change this behavior).
In vi mode the same CTRL-r and CTRL-s still work but there is another way more specific to vi mode.
Switch to command mode by hitting CTRL-[ or ESC and hit '/', then type a first few characters of 'iptables' command, like 'ipt' and hit return. Bash will display the most recent match found in history. To navigate around use 'n' or just plain '/' to repeat the search in the same direction, and 'N' or '?' to repeat the search in opposite direction!
With event designators you may execute only the most recently executed command matching (or starting with) 'string'.
Try '!iptables' history expansion command which refers to the most recent command starting with 'iptables'.
Another way is to use bash's built in 'history' command then grep for a string of interest and finally use an event designator in form '!N', where N is an integer which refers to N-th command in command history list.
For example,
$ history | grep 'ipt'
2 iptables -L -n -v -t nat
$ !2 # will execute the iptables command
I remembered another way to execute N-th command in history list in vi editing mode. Type 'N' (command number) and then 'G', in this example '2G'
Listing and Erasing Command History
Bash provides a built-in command 'history' for viewing and erasing command history.
Suppose that we are still working with the same example:
$ echo foo bar baz
$ iptables -L -n -v -t nat
$ ... lots and lots more commands
$ echo foo foo foo
$ perl -wle 'print q/hello world/'
$ awk -F: '{print$1}' /etc/passwd
$
Typing 'history' will display all the commands in bash history alongside with line numbers:
1 echo foo bar baz
2 iptables -L -n -v -t nat
... lots and lots more commands
568 echo foo foo foo
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
Typing 'history N', where N is an integer, will display the last N commands in the history.
For example, 'history 3' will display:
568 echo foo foo foo
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
history -c will clear the history list and history -d N will delete a history entry N.
By default, the history list is kept in user's home directory in a file '.bash_history'.
History Expansion
History expansion is done via so-called event designators and word designators. Event designators can be used to recall previously executed commands (events) and word designators can be used to extract command line arguments from the events. Optionally, various modifiers can be applied to the extracted arguments.
Event designators are special commands that begin with a '!' (there is also one that begins with a '^'), they may follow a word designator and one or more modifiers. Event designators, word designators and modifiers are separated by a colon ':'.
Event Designators
Lets look at a couple of examples to see how the event designators work.
Event designator '!!' can be used to refer to the previous command, for example,
$ echo foo bar baz
foo bar baz
$ !!
foo bar baz
Here the '!!' executed the previous 'echo foo bar baz' command.
Event designator '!N' can be used to refer to the N-th command.
Suppose you listed the history and got the following output:
1 echo foo foo foo
2 iptables -L -n -v -t nat
... lots and lots more commands
568 echo bar bar bar
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
Then the event designator '!569' will execute 'perl ...' command, and '!1' will execute 'echo foo foo foo' command!
Event designator '!-N' refers to current command line minus N. For example,
$ echo foo bar baz
foo bar baz
$ echo a b c d e
a b c d e
$ !-2
foo bar baz
Here the event designator '!-2' executed a one before the previous command, or current command line minus 2.
Event designator '!string' refers to the most recent command starting with 'string'. For example,
$ awk --help
$ perl --help
Then the event designator '!p' or '!perl' or '!per' will execute the 'perl --help' command. Similarly, '!a' will execute the awk command.
An event designator '!?string?' refers to a command line containing (not necessarily starting with) 'string'.
Perhaps the most interesting event designator is the one in form '^string1^string2^' which takes the last command, replaces string1 with string2 and executes it. For example,
$ ehco foo bar baz
bash: ehco: command not found
$ ^ehco^echo^
foo bar baz
Here the '^ehco^echo^' designator replaced the incorrectly typed 'ehco' command with the correct 'echo' command and executed it.
Word Designators and Modifiers
Word designators follow event designators separated by a colon. They are used to refer to some or all of the parameters on the command referenced by event designator.
For example,
$ echo a b c d e
a b c d e
$ echo !!:2
b
This is the simplest form of a word designator. ':2' refers to the 2nd argument of the command (3rd word). In general ':N' refers to Nth argument of the command ((N+1)-th word).
Word designators also accept ranges, for example,
$ echo a b c d e
a b c d e
$ echo !!:3-4
c d
There are various shortcuts, such as, ':$' to refer to the last argument, ':^' to refer to the first argument, ':*' to refer to all the arguments (synonym to ':1-$'), and others. See the cheat sheet for a complete list.
Modifiers can be used to modify the behavior of a word designators. For example:
$ tar -xvzf software-1.0.tgz
software-1.0/file
...
$ cd !!:$:r
software-1.0$
Here the 'r' modifier was applied to a word designator which picked the last argument from the previous command line. The 'r' modifier removed the trailing suffix '.tgz'.
The 'h' modifier removes the trailing pathname component, leaving the head:
$ echo /usr/local/apache
/usr/local/apache
$ echo !!:$:h
/usr/local
The 'e' modifier removes all but the trailing suffix:
$ ls -la /usr/src/software-4.2.messy-Extension
...
$ echo /usr/src/*!!:$:e
/usr/src/*.messy-Extension # ls could have been used instead of echo
Another interesting modifier is the substitute ':s/old/new/' modifier which substitutes new for old. It can be used in conjunction with 'g' modifier to do global substitution. For example,
$ ls /urs/local/software-4.2 /urs/local/software-4.3
/usr/bin/ls: /urs/local/software-4.2: No such file or directory
/usr/bin/ls: /urs/local/software-4.3: No such file or directory
$ !!:gs/urs/usr/
...
This example replaces all occurances of 'urs' to 'usr' and makes the command correct.
There are a few other modifiers, such as 'p' modifier which prints the resulting command after history expansion but does not execute it. See the cheat sheet for all of the modifiers.
Modifying History Behavior
Bash allows you to modify which commands get stored in the history list, the file where they get stored, the number of commands that get stored, and a few other options.
These options are controlled by setting HISTFILE, HISTFILESIZE, HISTIGNORE and HISTSIZE environment variables.
HISTFILE, as the name suggests, controls where the history file gets saved.
For example,
$ export HISTFILE=/home/pkrumins/todays_history
will save the commands to a file /home/pkrumins/todays_history
Set it to /dev/null or unset it to avoid getting your history list saved.
HISTFILESIZE controls how many history commands to keep in HISTFILE.
For example,
$ export HISTFILESIZE=1000
will keep the last 1000 history commands.
HISTSIZE controls how many history commands to keep in the history list of current session.
For example,
$ export HISTSIZE=42
will keep 42 last commands in the history of current session.
If this number is less than HISTFILESIZE, only that many commands will get written to HISTFILE.
HISTIGNORE controls the items which get ignored and do not get saved. This variable takes a list of colon separated patterns. Pattern '&' (ampersand) is special in a sense that it matches the previous history command.
There is a trick to make history ignore the commands which begin with a space. The pattern for that is "[ ]*"
For example,
$ export HISTIGNORE="&:[ ]*:exit"
will make bash ignore duplicate commands, commands that begin with a space, and the 'exit' command.
There are several other options of interest controlled by the built-in 'shopt' command.
The options may be set by specifying '-s' parameter to the 'shopt' command, and may be unset by specifying '-u' parameter.
Option 'histappend' controls how the history list gets written to HISTFILE, setting the option will append history list of current session to HISTFILE, unsetting it (default) will make HISTFILE get overwritten each time.
For example, to set this option, type:
$ shopt -s histappend
And to unset it, type:
$ shopt -u histappend
Option 'histreedit' allows users to re-edit a failed history substitution.
For example, suppose you had typed:
$ echo foo bar baz
and wanted to substitute 'baz' for 'test' with the ^baz^test^ event designator , but you made a mistake and typed ^boo^test^. This would lead to a substitution failure because the previous command does not contain string 'boo'.
If you had this option turned on, bash would put the erroneous ^baz^test^ event designator back on the command line as if you had typed it again.
Finally, option 'histverify' allows users to verify a substituted history expansion.
Based on the previous example, suppose you wanted to execute that 'echo' command again by using the '!!' event designator. If you had this option on, bash would not execute the 'echo' command immediately but would first put it on command line so that you could see if it had made the correct substitution.
Tuning the Command Prompt
Here is how my command prompt looks:
Wed Jan 30@07:07:03
pkrumins@catonmat:1002:2:~$
The first line displays the date and time the command prompt was displayed so I could keep track of commands back in time.
The second line displays username, hostname, global history number and current command number.
The global history number allows me to quickly use event designators.
My PS1, primary prompt display variable looks like this:
PS1='\d@\t\n\u@\h:\!:\#:\w$ '
Bash History Cheat Sheet
Here is a summary cheat sheet for working effectively with bash history.
This cheat sheet includes:
History editing keyboard shortcuts (emacs and vi mode),
History expansion summary - event designators, word designators and modifiers,
Shell variables and `shopt' options to modify history behavior,
Examples
Let me teach you how to work efficiently with command line history in bash.
This tutorial comes with a downloadable cheat sheet that summarizes (and expands on) topics covered here (scroll to the end for a download link).
In case you are a first time reader, this is the 3rd part of the article series on working efficiently in bourne again shell. Previously I have written on how to work efficiently in vi and emacs command editing modes by using predefined keyboard shortcuts (both articles come with cheat sheets of predefined shortcuts).
First, lets review some basic keyboard shortcuts for navigating around previously typed commands.
As you remember, bash offers two modes for command editing - emacs mode and vi mode. In each of these editing modes the shortcuts for retrieving history are different.
Suppose you had executed the following commands:
$ echo foo bar baz
$ iptables -L -n -v -t nat
$ ... lots and lots more commands
$ echo foo foo foo
$ perl -wle 'print q/hello world/'
$ awk -F: '{print$1}' /etc/passwd
$
and you wanted to execute the last command (awk -F ...).
You could certainly hit the up arrow and live happily along, but do you really want to move your hand that far away?
If you are in emacs mode just try CTRL-p which fetches the previous command from history list (CTRL-n for the next command).
In vi mode try CTRL-[ (or ESC) (to switch to command mode) and 'h' ('j' for the next command).
There is another, equally quick, way to do that by using bash's history expansion mechanism - event designators. Typing '!!' will execute the previous command (more about event designators later).
Now, suppose that you wanted to execute 'iptables -L -n -v -t nat' command again without retyping it.
A naive user would, again, just keep hitting up-arrow key until he/she finds the command. But that's not the way hackers work. Hackers love to work quickly and efficiently. Forget about arrow keys and page-up, page-down, home and end keys. They are completely useless and, as I said, they are too far off from the main part of the keyboard anyway.
In emacs mode try CTRL-r and type a few first letters of 'iptables', like 'ipt'. That will display the last iptables command you executed. In case you had more than one iptables commands executed in between, hitting CTRL-r again will display older entries. In case you miss the right command and move too deep into history list, you can reverse the search direction by hitting CTRL-s (don't forget that by default CTRL-s stops the output to the terminal and you'll get an effect of "frozen" terminal (hit CTRL-q to "unfreeze"), see stty command to change this behavior).
In vi mode the same CTRL-r and CTRL-s still work but there is another way more specific to vi mode.
Switch to command mode by hitting CTRL-[ or ESC and hit '/', then type a first few characters of 'iptables' command, like 'ipt' and hit return. Bash will display the most recent match found in history. To navigate around use 'n' or just plain '/' to repeat the search in the same direction, and 'N' or '?' to repeat the search in opposite direction!
With event designators you may execute only the most recently executed command matching (or starting with) 'string'.
Try '!iptables' history expansion command which refers to the most recent command starting with 'iptables'.
Another way is to use bash's built in 'history' command then grep for a string of interest and finally use an event designator in form '!N', where N is an integer which refers to N-th command in command history list.
For example,
$ history | grep 'ipt'
2 iptables -L -n -v -t nat
$ !2 # will execute the iptables command
I remembered another way to execute N-th command in history list in vi editing mode. Type 'N' (command number) and then 'G', in this example '2G'
Listing and Erasing Command History
Bash provides a built-in command 'history' for viewing and erasing command history.
Suppose that we are still working with the same example:
$ echo foo bar baz
$ iptables -L -n -v -t nat
$ ... lots and lots more commands
$ echo foo foo foo
$ perl -wle 'print q/hello world/'
$ awk -F: '{print$1}' /etc/passwd
$
Typing 'history' will display all the commands in bash history alongside with line numbers:
1 echo foo bar baz
2 iptables -L -n -v -t nat
... lots and lots more commands
568 echo foo foo foo
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
Typing 'history N', where N is an integer, will display the last N commands in the history.
For example, 'history 3' will display:
568 echo foo foo foo
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
history -c will clear the history list and history -d N will delete a history entry N.
By default, the history list is kept in user's home directory in a file '.bash_history'.
History Expansion
History expansion is done via so-called event designators and word designators. Event designators can be used to recall previously executed commands (events) and word designators can be used to extract command line arguments from the events. Optionally, various modifiers can be applied to the extracted arguments.
Event designators are special commands that begin with a '!' (there is also one that begins with a '^'), they may follow a word designator and one or more modifiers. Event designators, word designators and modifiers are separated by a colon ':'.
Event Designators
Lets look at a couple of examples to see how the event designators work.
Event designator '!!' can be used to refer to the previous command, for example,
$ echo foo bar baz
foo bar baz
$ !!
foo bar baz
Here the '!!' executed the previous 'echo foo bar baz' command.
Event designator '!N' can be used to refer to the N-th command.
Suppose you listed the history and got the following output:
1 echo foo foo foo
2 iptables -L -n -v -t nat
... lots and lots more commands
568 echo bar bar bar
569 perl -wle 'print q/hello world/'
570 awk -F: '{print$1}' /etc/passwd
Then the event designator '!569' will execute 'perl ...' command, and '!1' will execute 'echo foo foo foo' command!
Event designator '!-N' refers to current command line minus N. For example,
$ echo foo bar baz
foo bar baz
$ echo a b c d e
a b c d e
$ !-2
foo bar baz
Here the event designator '!-2' executed a one before the previous command, or current command line minus 2.
Event designator '!string' refers to the most recent command starting with 'string'. For example,
$ awk --help
$ perl --help
Then the event designator '!p' or '!perl' or '!per' will execute the 'perl --help' command. Similarly, '!a' will execute the awk command.
An event designator '!?string?' refers to a command line containing (not necessarily starting with) 'string'.
Perhaps the most interesting event designator is the one in form '^string1^string2^' which takes the last command, replaces string1 with string2 and executes it. For example,
$ ehco foo bar baz
bash: ehco: command not found
$ ^ehco^echo^
foo bar baz
Here the '^ehco^echo^' designator replaced the incorrectly typed 'ehco' command with the correct 'echo' command and executed it.
Word Designators and Modifiers
Word designators follow event designators separated by a colon. They are used to refer to some or all of the parameters on the command referenced by event designator.
For example,
$ echo a b c d e
a b c d e
$ echo !!:2
b
This is the simplest form of a word designator. ':2' refers to the 2nd argument of the command (3rd word). In general ':N' refers to Nth argument of the command ((N+1)-th word).
Word designators also accept ranges, for example,
$ echo a b c d e
a b c d e
$ echo !!:3-4
c d
There are various shortcuts, such as, ':$' to refer to the last argument, ':^' to refer to the first argument, ':*' to refer to all the arguments (synonym to ':1-$'), and others. See the cheat sheet for a complete list.
Modifiers can be used to modify the behavior of a word designators. For example:
$ tar -xvzf software-1.0.tgz
software-1.0/file
...
$ cd !!:$:r
software-1.0$
Here the 'r' modifier was applied to a word designator which picked the last argument from the previous command line. The 'r' modifier removed the trailing suffix '.tgz'.
The 'h' modifier removes the trailing pathname component, leaving the head:
$ echo /usr/local/apache
/usr/local/apache
$ echo !!:$:h
/usr/local
The 'e' modifier removes all but the trailing suffix:
$ ls -la /usr/src/software-4.2.messy-Extension
...
$ echo /usr/src/*!!:$:e
/usr/src/*.messy-Extension # ls could have been used instead of echo
Another interesting modifier is the substitute ':s/old/new/' modifier which substitutes new for old. It can be used in conjunction with 'g' modifier to do global substitution. For example,
$ ls /urs/local/software-4.2 /urs/local/software-4.3
/usr/bin/ls: /urs/local/software-4.2: No such file or directory
/usr/bin/ls: /urs/local/software-4.3: No such file or directory
$ !!:gs/urs/usr/
...
This example replaces all occurances of 'urs' to 'usr' and makes the command correct.
There are a few other modifiers, such as 'p' modifier which prints the resulting command after history expansion but does not execute it. See the cheat sheet for all of the modifiers.
Modifying History Behavior
Bash allows you to modify which commands get stored in the history list, the file where they get stored, the number of commands that get stored, and a few other options.
These options are controlled by setting HISTFILE, HISTFILESIZE, HISTIGNORE and HISTSIZE environment variables.
HISTFILE, as the name suggests, controls where the history file gets saved.
For example,
$ export HISTFILE=/home/pkrumins/todays_history
will save the commands to a file /home/pkrumins/todays_history
Set it to /dev/null or unset it to avoid getting your history list saved.
HISTFILESIZE controls how many history commands to keep in HISTFILE.
For example,
$ export HISTFILESIZE=1000
will keep the last 1000 history commands.
HISTSIZE controls how many history commands to keep in the history list of current session.
For example,
$ export HISTSIZE=42
will keep 42 last commands in the history of current session.
If this number is less than HISTFILESIZE, only that many commands will get written to HISTFILE.
HISTIGNORE controls the items which get ignored and do not get saved. This variable takes a list of colon separated patterns. Pattern '&' (ampersand) is special in a sense that it matches the previous history command.
There is a trick to make history ignore the commands which begin with a space. The pattern for that is "[ ]*"
For example,
$ export HISTIGNORE="&:[ ]*:exit"
will make bash ignore duplicate commands, commands that begin with a space, and the 'exit' command.
There are several other options of interest controlled by the built-in 'shopt' command.
The options may be set by specifying '-s' parameter to the 'shopt' command, and may be unset by specifying '-u' parameter.
Option 'histappend' controls how the history list gets written to HISTFILE, setting the option will append history list of current session to HISTFILE, unsetting it (default) will make HISTFILE get overwritten each time.
For example, to set this option, type:
$ shopt -s histappend
And to unset it, type:
$ shopt -u histappend
Option 'histreedit' allows users to re-edit a failed history substitution.
For example, suppose you had typed:
$ echo foo bar baz
and wanted to substitute 'baz' for 'test' with the ^baz^test^ event designator , but you made a mistake and typed ^boo^test^. This would lead to a substitution failure because the previous command does not contain string 'boo'.
If you had this option turned on, bash would put the erroneous ^baz^test^ event designator back on the command line as if you had typed it again.
Finally, option 'histverify' allows users to verify a substituted history expansion.
Based on the previous example, suppose you wanted to execute that 'echo' command again by using the '!!' event designator. If you had this option on, bash would not execute the 'echo' command immediately but would first put it on command line so that you could see if it had made the correct substitution.
Tuning the Command Prompt
Here is how my command prompt looks:
Wed Jan 30@07:07:03
pkrumins@catonmat:1002:2:~$
The first line displays the date and time the command prompt was displayed so I could keep track of commands back in time.
The second line displays username, hostname, global history number and current command number.
The global history number allows me to quickly use event designators.
My PS1, primary prompt display variable looks like this:
PS1='\d@\t\n\u@\h:\!:\#:\w$ '
Bash History Cheat Sheet
Here is a summary cheat sheet for working effectively with bash history.
This cheat sheet includes:
History editing keyboard shortcuts (emacs and vi mode),
History expansion summary - event designators, word designators and modifiers,
Shell variables and `shopt' options to modify history behavior,
Examples
Bash History: Display Date And Time For Each Command
Bash History: Display Date And Time For Each Command
How do I display shell command history with date and time under UNIX or Linux operating systems?
If the HISTTIMEFORMAT is set, the time stamp information associated with each history entry is written to the history file, marked with the history comment character. Defining the environment variable as follows:
$ HISTTIMEFORMAT="%d/%m/%y %T "
OR
$ echo 'export HISTTIMEFORMAT="%d/%m/%y %T "' >> ~/.bash_profile
Where,
%d - Day
%m - Month
%y - Year
%T - Time
To see history type
$ history
Sample outputs:
....
..
986 11/03/10 04:31:36 memcached-tool 10.10.28.22:11211 stats
987 11/03/10 04:31:36 w
988 11/03/10 04:31:37 iostat
989 11/03/10 04:31:37 top
990 11/03/10 04:31:37 at
991 11/03/10 04:31:38 atop
992 11/03/10 04:31:40 collectl
993 11/03/10 04:31:41 grep CPU /proc/cpuinfo
994 11/03/10 04:31:45 vmstat 3 100
995 11/03/10 04:31:55 sar -W -f /var/log/sa/sa12
....
..
References:
For more info type the following commands:
man bash
help history
man 3 strftime
How do I display shell command history with date and time under UNIX or Linux operating systems?
If the HISTTIMEFORMAT is set, the time stamp information associated with each history entry is written to the history file, marked with the history comment character. Defining the environment variable as follows:
$ HISTTIMEFORMAT="%d/%m/%y %T "
OR
$ echo 'export HISTTIMEFORMAT="%d/%m/%y %T "' >> ~/.bash_profile
Where,
%d - Day
%m - Month
%y - Year
%T - Time
To see history type
$ history
Sample outputs:
....
..
986 11/03/10 04:31:36 memcached-tool 10.10.28.22:11211 stats
987 11/03/10 04:31:36 w
988 11/03/10 04:31:37 iostat
989 11/03/10 04:31:37 top
990 11/03/10 04:31:37 at
991 11/03/10 04:31:38 atop
992 11/03/10 04:31:40 collectl
993 11/03/10 04:31:41 grep CPU /proc/cpuinfo
994 11/03/10 04:31:45 vmstat 3 100
995 11/03/10 04:31:55 sar -W -f /var/log/sa/sa12
....
..
References:
For more info type the following commands:
man bash
help history
man 3 strftime
Código decompilado do Stuxnet que está disponível
código decompilado do Stuxnet que está disponível para download no seguinte site: https://github.com/Laurelai/decompile-dump
OBS: Este blog apenas cita como forma de uso e aprendizado acadêmico, não de forma ilegal.
OBS: Este blog apenas cita como forma de uso e aprendizado acadêmico, não de forma ilegal.
Assinar:
Postagens (Atom)