`history -r` can not read from /dev/stdin ?
I was trying to reload the bash history file which changed by another bash session with the following commands, but it wouldn't work, please help me, why? ``` new_history=$(history -a /dev/stdout) history -c history -r echo "$new_history" | history -r /dev/stdin ```
Re: `history -r` can not read from /dev/stdin ?
2012/8/17 Chet Ramey : > On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote: >> I was trying to reload the bash history file which changed by another >> bash session with the following commands, but it wouldn't work, please >> help me, why? >> >> ``` >> new_history=$(history -a /dev/stdout) >> history -c >> history -r >> echo "$new_history" | history -r /dev/stdin >> ``` > > One possible cause that springs to mind is the fact that the `history -r' > at the end of the pipeline is run in a subshell and cannot affect its > parent's history list. > > > > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ So, How could I accomplish this kind of thing?
Re: `history -r` can not read from /dev/stdin ?
2012/8/17 Chet Ramey : > On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote: >> 2012/8/17 Chet Ramey : >>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote: >>>> I was trying to reload the bash history file which changed by another >>>> bash session with the following commands, but it wouldn't work, please >>>> help me, why? >>>> >>>> ``` >>>> new_history=$(history -a /dev/stdout) >>>> history -c >>>> history -r >>>> echo "$new_history" | history -r /dev/stdin >>>> ``` >>> >>> One possible cause that springs to mind is the fact that the `history -r' >>> at the end of the pipeline is run in a subshell and cannot affect its >>> parent's history list. >> >> So, How could I accomplish this kind of thing? > > Why not just use a regular file? > > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ Actually, I was tring to erase duplicate entries and share history across bash sessions.'erasedups' in `HISTCONTROL` only have effect for history list in the memory, so my solution is to load entire history file into memory and save it after every command finished. Here is what I am currently have in .bashrc, and it works as expected. reload_history() { local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then history -w # This is necessay because we need # to clear the last append signture history -c history -r else HISTTEMP=`mktemp` history -a $HISTTEMP history -c history -r history -r $HISTTEMP history -w rm $HISTTEMP fi HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` } export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND" Considering `mkemp` then remove the temp file on every prompt command is a little bit expensive, I want to directly pipe the output of the `history -a` to `hisotory -r` like below, unfortunately, this wouldn't work, because `history -r` could not handle /dev/stdin. reload_history() { local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then history -w # This is necessay because we need # to clear the last append signture history -c history -r else new_history=$(history -a /dev/stdout) history -c history -r echo "$new_history" | history -r /dev/stdin history -w fi HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` } export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND"
Re: `history -r` can not read from /dev/stdin ?
2012/8/17 郑文辉(Techlive Zheng) : > 2012/8/17 Chet Ramey : >> On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote: >>> 2012/8/17 Chet Ramey : >>>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote: >>>>> I was trying to reload the bash history file which changed by another >>>>> bash session with the following commands, but it wouldn't work, please >>>>> help me, why? >>>>> >>>>> ``` >>>>> new_history=$(history -a /dev/stdout) >>>>> history -c >>>>> history -r >>>>> echo "$new_history" | history -r /dev/stdin >>>>> ``` >>>> >>>> One possible cause that springs to mind is the fact that the `history -r' >>>> at the end of the pipeline is run in a subshell and cannot affect its >>>> parent's history list. >>> >>> So, How could I accomplish this kind of thing? >> >> Why not just use a regular file? >> >> -- >> ``The lyf so short, the craft so long to lerne.'' - Chaucer >> ``Ars longa, vita brevis'' - Hippocrates >> Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ > > Actually, I was tring to erase duplicate entries and share history > across bash sessions.'erasedups' in `HISTCONTROL` only have effect for > history list in the memory, so my solution is to load entire history > file into memory and save it after every command finished. > > Here is what I am currently have in .bashrc, and it works as expected. > > reload_history() { > local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` > if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then > history -w > # This is necessay because we need > # to clear the last append signture > history -c > history -r > else > HISTTEMP=`mktemp` > history -a $HISTTEMP > history -c > history -r > history -r $HISTTEMP > history -w > rm $HISTTEMP > fi > HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` > } > > export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND" > > Considering `mkemp` then remove the temp file on every prompt command > is a little bit expensive, I want to directly pipe the output of the > `history -a` to `hisotory -r` like below, unfortunately, this wouldn't > work, because `history -r` could not handle /dev/stdin. > > reload_history() { > local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` > if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then > history -w > # This is necessay because we need > # to clear the last append signture > history -c > history -r > else > new_history=$(history -a /dev/stdout) > history -c > history -r > echo "$new_history" | history -r /dev/stdin > history -w > fi > HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` > } > > export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND" I have just checked out the source of bash and found that `read()` or `mmap` is used to read the history file as below. The following code could not handle /dev/stdin properly. As I am not a C expert, I could not come up a patch for this, maybe someone here could give me a little help? >From lib/readline/histfile.c:200 #ifdef HISTORY_USE_MMAP /* We map read/write and private so we can change newlines to NULs without affecting the underlying object. */ buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0); if ((void *)buffer == MAP_FAILED) { errno = overflow_errno; goto error_and_exit; } chars_read = file_size; #else buffer = (char *)malloc (file_size + 1); if (buffer == 0) { errno = overflow_errno; goto error_and_exit; } chars_read = read (file, buffer, file_size); #endif
Re: `history -r` can not read from /dev/stdin ?
2012/8/17 郑文辉(Techlive Zheng) : > 2012/8/17 郑文辉(Techlive Zheng) : >> 2012/8/17 Chet Ramey : >>> On 8/16/12 10:11 PM, 郑文辉(Techlive Zheng) wrote: >>>> 2012/8/17 Chet Ramey : >>>>> On 8/16/12 9:17 AM, 郑文辉(Techlive Zheng) wrote: >>>>>> I was trying to reload the bash history file which changed by another >>>>>> bash session with the following commands, but it wouldn't work, please >>>>>> help me, why? >>>>>> >>>>>> ``` >>>>>> new_history=$(history -a /dev/stdout) >>>>>> history -c >>>>>> history -r >>>>>> echo "$new_history" | history -r /dev/stdin >>>>>> ``` >>>>> >>>>> One possible cause that springs to mind is the fact that the `history -r' >>>>> at the end of the pipeline is run in a subshell and cannot affect its >>>>> parent's history list. >>>> >>>> So, How could I accomplish this kind of thing? >>> >>> Why not just use a regular file? >>> >>> -- >>> ``The lyf so short, the craft so long to lerne.'' - Chaucer >>> ``Ars longa, vita brevis'' - Hippocrates >>> Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ >> >> Actually, I was tring to erase duplicate entries and share history >> across bash sessions.'erasedups' in `HISTCONTROL` only have effect for >> history list in the memory, so my solution is to load entire history >> file into memory and save it after every command finished. >> >> Here is what I am currently have in .bashrc, and it works as expected. >> >> reload_history() { >> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` >> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then >> history -w >> # This is necessay because we need >> # to clear the last append signture >> history -c >> history -r >> else >> HISTTEMP=`mktemp` >> history -a $HISTTEMP >> history -c >> history -r >> history -r $HISTTEMP >> history -w >> rm $HISTTEMP >> fi >> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` >> } >> >> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND" >> >> Considering `mkemp` then remove the temp file on every prompt command >> is a little bit expensive, I want to directly pipe the output of the >> `history -a` to `hisotory -r` like below, unfortunately, this wouldn't >> work, because `history -r` could not handle /dev/stdin. >> >> reload_history() { >> local HISTHASH_NEW=`md5sum $HOME/.bash_history | cut -d' ' -f1` >> if [ "$HISTHASH" = "$HISTHASH_NEW" ]; then >> history -w >> # This is necessay because we need >> # to clear the last append signture >> history -c >> history -r >> else >> new_history=$(history -a /dev/stdout) >> history -c >> history -r >> echo "$new_history" | history -r /dev/stdin >> history -w >> fi >> HISTHASH=`md5sum $HOME/.bash_history | cut -d' ' -f1` >> } >> >> export PROMPT_COMMAND="reload_history;$PROMPT_COMMAND" > > I have just checked out the source of bash and found that `read()` or > `mmap` is used to read the history file as below. The following code > could not handle /dev/stdin properly. As I am not a C expert, I could > not come up a patch for this, maybe someone here could give me a > little help? > > From lib/readline/histfile.c:200 > > #ifdef HISTORY_USE_MMAP > /* We map read/write and private so we can change newlines to NULs without > affecting the underlying object. */ > buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, > MAP_RFLAGS, file, 0); > if ((void *)buffer == MAP_FAILED) > { > errno = overflow_errno; > goto error_and_exit; > } > chars_read = file_size; > #else > buffer = (char *)malloc (file_size + 1); > if (buffer == 0) > { > errno = overflow_errno; > goto error_and_exit; > } > > chars_read = read (file, buffer, file_size); > #endif I have tried using a named pipe or process substition, neither worked.
`bash --debugger` in interactive mode
I happened to have `shopt -s extdebug` in my .bashrc recently. After a new bash session started, I got the following output. bash debugger, bashdb, release 4.2-0.8 Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Rocky Bernstein This is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. ** Internal debug error _Dbg_is_file(): file argument null bash: _Dbg_filenames[$fullname]: bad array subscript I guess `--debugger` or `shopt -s extdebug` is not supposed to be run under interactive mode? If so, maybe a detection should be done for this situation?
Re: `bash --debugger` in interactive mode
2012/8/20 Chet Ramey : > On 8/18/12 1:55 AM, 郑文辉(Techlive Zheng) wrote: >> I happened to have `shopt -s extdebug` in my .bashrc recently. >> >> After a new bash session started, I got the following output. >> >> bash debugger, bashdb, release 4.2-0.8 >> >> Copyright 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 >> Rocky Bernstein >> This is free software, covered by the GNU General Public License, >> and you are >> welcome to change it and/or distribute copies of it under certain >> conditions. >> >> ** Internal debug error _Dbg_is_file(): file argument null >> bash: _Dbg_filenames[$fullname]: bad array subscript >> >> I guess `--debugger` or `shopt -s extdebug` is not supposed to be run >> under interactive mode? >> >> If so, maybe a detection should be done for this situation? > > Thanks for the report. I will put something in for the next bash release. > > Chet >> > > > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ I just want poin it out that there are some bash tricks which require using `set -o functrace` and `shopt -s extdebug` in interactive mode to make the DEBUG trap to be invoked in ( ) subshells, see <https://github.com/revans/bash-it/blob/master/lib/preexec.bash#L115>, maybe this is something that should be done in `bashdb`?
Re: Indirect expansion and arrays
> On 7/29/10 4:55 PM, Bernd Eggink wrote: > > It seems that indirect expansion doesn't work with arrays: > > > > $ a=(x y z) > > $ b=a > > $ echo "${!b[0]} ${!b[1]} ${!b[2]}" > > x > > > > Is that intended? The documentation isn't explicit about it. > It does, but it doesn't work in the way you are trying. The `!' binds to > an entire variable reference, in this case 'b[0]'. The idea behind that > was to permit the use of an array of variable names, for instance, that > could be easily referenced using indirect expansion. > The following code will display > "x variable y variable z variable" > a=(x y z) > x='x variable' > y='y variable' > z='z variable' > echo "${!a[0]} ${!a[1]} ${!a[2]}" > Chet >-- >``The lyf so short, the craft so long to lerne.'' - Chaucer >``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRUc...@case.edu > http://cnswww.cns.cwru.edu/~chet/ I think that indirect reference for fash variable should be used literally. $ a=(x y z) $ b=a[@] $ echo "${!b}" # this would work Combine with Chet Ramey's reply, a strucure like below would work. $ c=(a[0] a[1] a[2]) $ echo "${!c[0]} ${!c[1]} ${!c[2]}" #this would work too -- View this message in context: http://old.nabble.com/Indirect-expansion-and-arrays-tp29300541p34504291.html Sent from the Gnu - Bash mailing list archive at Nabble.com.