Giter VIP home page Giter VIP logo

bash-preexec's People

Contributors

adamprice2 avatar adoyle-h avatar akinomyoga avatar ayeseeem avatar brandonweeks avatar calid avatar d630 avatar dimo414 avatar dseomn avatar evverx avatar franklinyu avatar gaelicwizard avatar haletom avatar ivuk avatar jimwins avatar jombooth avatar jordemort avatar lguelorget avatar matthias-bach-by avatar mschrage avatar phillipsz avatar rcaloras avatar spl avatar steinarvk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bash-preexec's Issues

preexec breaks passed-in environment variables when used with command builtin

I received this bug report for my script which uses the same trickery as bash-preexec:

https://gitlab.com/gnachman/iterm2/issues/3644

It seems that setting a DEBUG trap breaks this use case:

FOO=BAR command something_that_uses_foo.sh

To reproduce with bash-preexec:

echo 'echo $BUILD_SYSTEM' > p
chmod +x p

# Note that this prints "build/core"
BUILD_SYSTEM=build/core command ./p

# Now set up preexec and notice that it breaks
source ~/.bash-preexec.sh
function preexec() {
true
}

# This produces no output
BUILD_SYSTEM=build/core command ./p

This is a problem because it means preexec is incompatible with building Android, and who knows what else. Seems like a bug in bash, but I'm not much of a bash expert myself.

.bash_logout commands get called with preexec repeating the last command line if logging out with CTRL+D

When logging out from an Ubuntu ssh session with CTRL+D in an empty command line, the preexec function gets called with the previous "$1" while executing the line /usr/bin/clear_console -q from ~/.bash_logout.
For example:

$ ssh localhost
davefx@localhost's password: 
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-31-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

91 packages can be updated.
0 updates are security updates.

Last login: Mon Jul 25 07:59:53 2016 from 127.0.0.1
davefx@localhost:~ $ preexec() { echo «$1»; sleep 3; }
davefx@localhost:~ $ echo Hello
«echo Hello»
Hello
davefx@laetus:~ $ logout
«echo Hello»
Connection to localhost closed.
davefx@laetus:~ $ 

(The logout was generated pressing CTRL+D)

`preexec` doesn't work for function declarations

$ source .bash-preexec.sh
$ preexec() { echo "just typed $1"; }
$ date
just typed date
Wed Jun 17 16:20:15 UTC 2015
$ function foo() { echo foo; }
$ foo
just typed foo
foo
$ (date)
Wed Jun 24 02:42:48 UTC 2015

Whitespace is trimmed from commands

Whitespace is trimmed from commands. For instance, the command " foo " is recorded as "foo".

This whitespace is stripped when reading the line from the history with the "read" builtin.

Please add LICENSE file

Hi, there is no LICENSE file, which means that:

you retain all rights to your source code and that nobody else may reproduce, distribute, or create derivative works from your work. This might not be what you intend

https://help.github.com/articles/open-source-licensing/

Could you please add a LICENSE file? If you don't really care about how people use the code, choose something permissive like e.g. MIT license

Restore DEBUG trap preservation

PR #60 regressed the fix to #39. We need to identify a new mechanism to capture traps that avoids the issues discussed there.

As I understand it this is only an issue for users who erroneously export their PROMPT_COMMAND at some point in their .bashrc, so if we can detect that case we could simply not preserve traps for those users.

$this_command is interpreted by `echo`

A very small number of useless commands are ignored by bash-preexec, because they're passed to echo. E.g., the command line -n causes bash-preexec to run echo -n which does not print -n. The solution I've seen is to use printf '%s\n' ... instead of echo.

Detect readonly HISTTIMEFORMAT

I received an issue report from a user who had a read-only HISTTIMEFORMAT variable. It caused an error to be printed on every command executed. The issue report is here:

https://gitlab.com/gnachman/iterm2/issues/7028

You can reproduce it by doing

readonly HISTTIMEFORMAT

after loading bash-preexec, and you get this output on every command:

bash: HISTTIMEFORMAT: readonly variable

I'm not sure if bash lets you detect that the variable is readonly. I suppose the simplest fix would be to redirect the output of the assignment to /dev/null.

__bp_preexec_invoke_exec invoked on ctrl-C from command line

When the user ctrl-C at the bash prompt (e.g., begins typing a command, thinks better of it, and presses ctrl-C), the __bp_preexec_invoke_exec() function is invoked, and it finds the previous command from history. I've been unable to find a way for the __bp_preexec_invoke_exec() function to determine if it is invoked because of a command, or because the user hit control-c.

bash: read: read error: 0: Invalid argument

Hi,

Every now and then I get the following issue after pressing return on entering a new command:

bash: read: read error: 0: Invalid argument

I'm guessing that this bit of code is causing the issue:

__bp_in_prompt_command() {

    local prompt_command_array
    IFS=';' read -ra prompt_command_array <<< "$PROMPT_COMMAND"

I have changed the read part to be this:

    IFS=';' read -ra prompt_command_array 2>/dev/null <<< "$PROMPT_COMMAND"

and that seems to have squished the message for now. I'll keep an eye on things to see how it goes.

Thanks,

Rich

Instructions inconsistent with script comments

The project README.md clearly states:

It must be the last thing imported in your bash profile.

bash-preexec.sh itself states:

Sets our trap and __bp_install as part of our PROMPT_COMMAND to install
after our session has started. This allows bash-preexec to be inlucded
at any point in our bash profile.

This comment (which has a typo) seems to contradict the instructions from README.md.

The README.md instructions seem more correct; if bash-preexec.sh is not last, any subsequent changes to PROMPT_COMMAND will be lost. At the very least, the script comment is misleading.

Additionally, perhaps bash-preexec.sh could emit a warning if PROMPT_COMMAND has been modified between __bp_install_after_session_init() and __bp_install()? (I spent a while trying to figure out why https://github.com/rupa/z wasn't working on a system where an administrator (unbeknownst to me) included bash-preexec.sh via a chain of inclusions starting from /etc/bash.bashrc.)

This is not an issue

Hi,
I sent @rcaloras and email (the one on github). Its about something I am working on and is very close in its implementation to this project.

Cannot get true exit status

I run lots of scripts so Ive been wanting bash to update some things once its done.

doing a precmd() { updatestatus -green; echo $?; };

shows that Bash exit status is 0, even if I type false

bash-3.2$ false
0

injecting preexec function name into terminal when using editor

When editing a Bash command you can use Ctrl-x Ctrl-e to open the command in $EDITOR, which I have set to Vim. Once I am doing editing the command, i execute :wq to quit Vim and when I look at my terminal I see __bp_preexec_invoke_exec being injected into the output.

So for example if I create the command echo foo in vim then ran it, my output would look like

> echo foo
__bp_preexec_invoke_exec
foo

Any idea why this might be happening and is there a fix?

I am using bash 4.4

Conflicts with iTerm2 shell integration.

Causes: rcaloras/bashhub-client#27

Looks like both projects leverage the debug trap to create a preexec function. @gnachman any chance you could be convinced to use this library if it can provide everything you need for iTerm2's preexec functionality? I'm happy to make all the PRs :) I want to make sure Bashhub and iTerm2 can work together.

Quoted from #6

I'd love to fix up this project to make it compatible with the awesome iTerm2 :) I wrote bash-preexec to include function arrays and to avoid multiple inclusion which allows multiple shell integrations to add preexec functions triggered through one debug trap hook. Any chance you'd be willing to switch to this library if I make it compatible?

Thanks!

Install fails when bash is in POSIX mode

I run my bash in POSIX mode and noticed that the install step fails due to how trap is used (see Bash POSIX Mode).

To fix it, I did something like this:

case :$SHELLOPTS: in *:posix:*) posix=1;; esac
if [ "$posix" ]; then pre="set +o posix"; post="set -o posix"; fi
. bash-preexec.sh
PROMPT_COMMAND="$pre
$PROMPT_COMMAND
$post"

Maybe it would be useful to incorporate this into the script.

Question on HISTCONTROL

After adopting bash-preexec for a script I maintain, I received a bug report that it changes HISTCONTROL: https://gitlab.com/gnachman/iterm2/issues/5787#note_34771330

Based on the comment in the code, I think I'd rather preserve HISTCONTROL than get leading and trailing spaces correctly reported (I strip them anyway):

# Remove ignorespace and or replace ignoreboth from HISTCONTROL
# so we can accurately invoke preexec with a command from our
# history even if it starts with a space.

Is the comment accurate? Are there any traps if I remove the call to __bp_adjust_histcontrol? Will anything worse happen than losing some whitespace at the beginning of a command?

I tested it and it seems safe, but I thought I'd check before unleashing this change in prod.

Edit and execute command in editor

Bash -4.4

  1. press C-X,C-V to open an editor (vim in my case) and edit a command (e.g. 'uptime'), save and quit
  2. see the following output

$
uptime
__bp_preexec_invoke_exec "$_"
14:00 up 12:18, 2 users, load averages: 1.44 1.56 1.58

I believe the 3rd row is unwanted

Thanks!

Can I completely abort command execution?

Hello,

I'm trying to write a helper for certain commands in preexec, but when certain conditions are met I'd like to completely abort execution of the command.

Is this possible?

Thank you in advance!

bash 4.4: using $PS0

As far I can see, we may avoid the DEBUG trap in version 4.4:

       PS0    
             The value of this parameter is expanded  (see  PROMPTING
              below) and displayed by interactive shells after reading
              a command and before the command is executed.

PS0 is expanded before DEBUG

Pre-pend sudo to execution of binaries in /sbin

This is more of a support question. I'm wondering if this is a valid use case:

 precmd() {                                                                      
     cmdpath=`which $1`                                                          
     if [[ "$cmdpath" =~ "^(/usr)?/sbin/.*" ]]; then                             
         sudo $1                                                                 
     fi                                                                          
 }     

If I'm running anything in /sbin (requiring root) then I'd like to prepend sudo to the command automatically.

Preserve existing DEBUG traps

Currently bash-preexec clobbers existing DEBUG traps when it is sourced. Would you be interested in a PR that moves the contents of trap -p DEBUG into a function and appends it to preexec_functions?

commands with multiline strings are truncated to first line

Commands that contain multi-line strings are truncated to the first line. For instance, the following command

echo 'foo
bar'

results in this_command="echo 'foo" being passed to the preexec hooks. The "bar" part is entirely lost. This is because "read" only reads a single line.

Display command execution time

I want to display the time spent running a command. I've defined the following functions:

preexec () {
    date_before=$(date +%s.%N)
}

precmd () {
    if [ -z "$date_before" ]; then
        return 0
    fi

    local date_after
    date_after=$(date +%s.%N)
    printf "\n%.2fs\n\n" $(bc<<<$date_after-$date_before)
}

On bash version 4.3.33(1)-release (x86_64-apple-darwin14.1.0) on a mac works as expected. However, on a ubuntu 14.04 version 4.3.11(1)-release (x86_64-pc-linux-gnu) it doesn't.

It looks like the order of execution on mac is prexec -> precmd, while on linux is precmd - > preexec, but even if I swap the function names on linux it still doesn't work as expected.

Also, I've used gdate instead of date on mac. (from coreutils)

Any ideas how to make it work on linux?

bash-preexec fails if user has "nounset" option set

Some users set the bash option "nounset", which makes evaluating "${foo}" an error if there is no variable named "foo". When expanding as a string, "${foo:-}" can be used to explicitly indicate that it is okay for the variable to be unset and use an empty string instead.

This option currently makes bash-preexec fail all over the place, whether set -u is set before or after it is sourced. Unset variables are referenced many times during initialization and hook execution.

Each individual line is mostly easy to fix, but it's a pain to maintain. We cannot set "nounset" in bash-preexec.sh itself, because that would pollute the user's shell options in a potentially very annoying way. However, if we can configure the bats tests to run under "set -u", we should be able to maintain compatibility with this option.

(Preliminary testing indicates that bats 0.4.0 does not support set -u, but bats 1.1.0 from the bats-core fork does. We may have to change the way we install bats on travis for the necessary changes to the test environment to pass.)

It would be nice to also test "set -x", but even bats 1.1.0 does not seem to support that.

Can you cancel a command based on logic within preexec?

Hey guys,

Sorry if this already exists as an issue / question. I did some googling and read through the issues where and couldn't find a confirmation one way or another.

One thing that I'd like to do is possibly cancel a command altogether if some certain critera is met.
For example, I tried to run git push and hadn't run my linter yet, then I want it to break and not actually run git push.

Is there any way to handle this within preexec? It looked like the answer might be to hack something around your history and/or traps?

image

Thanks in advance for any advice on this!

[question] Modify command before invocation (but add an unmodified one to history)

Hello and thank you for you terrifically useful project! 🙂
One simple question regarding usage. Is it possible to do something with the command entered ($1 in preexec function) before it gets executed by the shell? My practical interest is to append time to every command, for example.
Thank you for your response in advance and have a good week!

Declaration of semicolon won't work.

When decelerating detecting semicolon as the first character and overnight default error message, the $1 variable it's empty.

.bashrc content append of:

preexec() {
                        if [ "$1" = ";" ]; then
               echo "$1 expression evaluated as true"
                        else
               echo "$1 expression evaluated as false"
            fi
          }


Incompatible prompt_command settings

Some users of a project I work on that's based on Bash-Preexec modify their prompt command in ~/.bashrc after sourcing the script. In some cases, we've found they'll do this:

PROMPT_COMMAND+="history -a"

This breaks BP, because prompt_command ends in "__bp_install", so on first execution, the user gets a
"no such command: __bp_installhistory" message.

To fix this particular issue, I suggest wrapping the prompt_command installed by bash_preexec in newlines, ie
__bp_preexec_foo_bar; __bp_install \n

so that appending to PROMPT_COMMAND won't cause problems. Newlines are in general the most universally compatible way of splitting commands in Bash, so we could consider using them wherever a problem might arise, ie,

\n __bp_preexec_foo_bar \n __bp_install \n

This way, even if someone does a PROMPT_COMMAND="echo good morning! $PROMPT_COMMAND", after sourcing bash-preexec, the result will still be correct.

w.r.t. testing this - it would be ideal to test various possible orderings of setting up custom prompt commands and sourcing Bash-Preexec, for example,

adjust PROMPT_COMMAND
source bash_preexec
adjust PROMPT_COMMAND again

source bash_preexec
adjust PROMPT_COMMAND

FreeBSD sed doesn't seem to support \+

I'm using FreeBSD 11.2-RELEASE-p8, and the first argument passed to preexec functions is wrong:

153462@davidmandelberg:~$ HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9]\+[* ] //'
  812  HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9]\+[* ] //'

Here are two variations that do work:

153462@davidmandelberg:~$ HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9]\{1,\}[* ] //'                                                                                                                                                                                                                                 
HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9]\{1,\}[* ] //'
153462@davidmandelberg:~$ HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'                                                                                                                                                                                                                                 
HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'

Tagging @steinarvk, @d630, and @dimo414 because of #87 and #88.

Preserved DEBUG traps should be invoked every time, not just on preexec

A coworker pointed out that that the fix to #39 doesn't properly preserve the behavior of the DEBUG trap, because preexec only triggers on interactive prompts, whereas before installation the command was triggered on every DEBUG event.

I think this can be fixed by simply moving the old DEBUG trap out of preexec_functions and instead eval-ing it at the beginning of __bp_preexec_invoke_exec - before the short-circuiting checks are made.

The only problem with this is it makes it difficult for someone to clean up the old trap - it's no longer in the trap itself nor in the preexec / preexec_functions, but some other variable. It's simple enough to document that (e.g. "The old DEBUG trap will be preserved in a bp_prior_debug_trap variable") but that widens the API surface and might be abused.

I'll prepare a patch, but I wanted to get some opinions on the approach first.

sed -E does not work with older versions of sed

This is an issue introduced with my earlier commit 1c9db27 . It uses the -E flag for sed (--regexp-extended), but this is not supported by every version of sed. Specifically I've observed it to fail on GNU sed 4.1.3.

It's probably better to use a variant of d630's suggestion from #79 .

Preexec before SSH command

Hello,

I'm trying to change my tmux window name on the fly when i'm connecting to another server through SSH.
I tried the following :

preexec() { if [ "$1" == "ssh" ]; then tmux rename-window $3@$1; else tmux rename-window $(whoami)@$(hostname); fi }

After trying ssh myhost -l myuser
Preexec does not seem to be executed ...

Am i missing something ?

Thank you, regards, Greg.

Check to make sure History is enabled.

Several history features should be checked or enabled to make sure bash-preexec can operate correctly.

One example is simply making sure history is turned on.

history_check=$(set -o | grep history)
if [[ "$history_check" == "history off" ]]; then
   echo "Enable history to use bash preexec"
   return 1
fi;

Quoted by @evverx on #6 :

@rcaloras , thanks.
Could probably add a few more checks to make sure history is properly enabled

Too many checks: history on, HISTSIZE, history-size in ~/.inputrc...

I vote for auto enabling:)

I've collected some useful settings:

# enable access to the command history
set -o history

# save each line of a multi-line command in the same history entry
shopt -s cmdhist

# save the command with embedded newlines instead of semicolons
shopt -s lithist

# save lines which begin with a space character in the history list
# preserve dups!
HISTCONTROL= # already done

# save all lines in the history list
HISTIGNORE=

# every command being saved on the history list (there is no limit)
HISTSIZE=-1
bind 'set history-size -1'

Incompatibility with "z"

Steps to reproduce:

  1. Install "z" from https://github.com/rupa/z
  2. Source "z" before "bash-preexec"
  3. Start new shell session

Actual result:

  1. The precmd function is executed
  2. The preexec function is executed with last command from history

Expected result:

  1. The precmd function is executed

Doesn't actually work at all

$ source .bash-preexec.sh
$ preexec() { echo "just typed $1"; }
$ date

Fri Oct  7 11:42:38 BST 2016

Here is my Bash version (installed via Homebrew):

GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin15.4.0)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Here is the bash location:

/usr/local/bin/bash

preexec_function gets inaccurate arguments in tmux

Observed problem: Exiting from tmux executes all preexec_functions with the previous command.

Expected behavior: $1 should probably be empty or "logout", since that's what tmux briefly shows on my screen before exiting.

Steps to reproduce:

$ git -C ~/src/bash-preexec describe --tags
0.3.6
$ tmux -V
tmux 2.6
$ tmux
tmux $ foo() { echo "$@" >> preexec.out; }
tmux $ preexec_functions+=(foo)
tmux $ echo 123
<CTRL + D>
$ cat preexec.out
echo 123
echo 123

If you tail -f preexec.out while performing these steps, you see that the second echo 123 does indeed come from the <CTRL + D>.

Is it possible to abort several simple commands typed into the command line altogether?

As shown in # 37, enabling extdebug using the shopt utility and return a non-zero status from the preexec function would cause the next simple command to be skipped. Is it possible to abort several simple commands typed into the command line altogether, which are separated by the control operators such as ";"?

For example, if I typed "uptime; df -h", the first command "uptime" is skipped. However, "df -h" still gets executed. Is it possible to also skip the second simple command?

bash-preexec

Hey,

I have forked your project and modified it to my needs. Have a look at it, if you like.

Cheers

Doesn't work in scripts

I'd like to ship preexec with somethin I'm working on, just to run it in a script.
It doesn't work at all if I source bash-preexec.sh at the top of the script.

cat my-script.sh

SCRIPTLOCATION="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$SCRIPTLOCATION/bash-preexec.sh"
...
preexec(){ 
	if [[ "$1" == "git"* ]]; then 
		echo -e "$Blue > $1$reset"
	fi
git status 
...
}

Stops triggering precmd every once in a while

So I've noticed that every once in a while (it seems random, although maybe we'll discover there's something I'm doing that's causing this problem), my shell will stop updating the prompt (PS1)

I use https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh in order to display git branch information within my prompt and so this is where I usually first notice the issue of precmd not being executed as I'll switch between branches and find the branch name stays the same. But unfortunately that means the issue could have occurred at some earlier point in time.

Here's my .bashrc so you can see how it's configured

The reason I believe it's precmd not being triggered, is I adding in an echo to see what it was doing and I found it was no longer showing the echo and so subsequently I presume no longer calling my prompt function which sets the PS1.

precmd() { echo 'do stuff'; prompt; }

I've tried unsetting PS1 manually and then setting it again (pretty much as my prompt function does). I've tried using the reset command or source ~/.bashrc and source ~/.bash-preexec.sh (also tried source ~/.git-prompt.sh in case that was having issues). But no luck in getting precmd to start running again.

The only thing I'm able to do is to open a new terminal tab and then move back in the directory I was just in and then close the original tab I had open :-(

Any help you can give me in identifying what part of my bashrc might be causing the issue would be appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.