Искаженная история

Можно использовать дескриптор файла чтения-записи удара для открытия файла (для перезаписи его на месте), затем sed и truncate ... но конечно, никогда не позволяйте Вашим изменениям быть больше, чем чтение объема данных до сих пор.

Вот сценарий (использование: колотите переменный $BASHPID),

# Create a test file
  echo "going abc"  >junk
  echo "going def" >>junk
  echo "# ORIGINAL file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )
#
# Assign file to fd 3, and open it r/w
  exec 3<> junk  
#
# Choose a unique filename to hold the new file size  and the pid 
# of the semi-asynchrounous process to which 'tee' streams the new file..  
  [[ ! -d "/tmp/$USER" ]] && mkdir "/tmp/$USER" 
  f_pid_size="/tmp/$USER/pid_size.$(date '+%N')" # %N is a GNU extension: nanoseconds
  [[ -f "$f_pid_size" ]] && { echo "ERROR: Work file already exists: '$f_pid_size'" ;exit 1 ; }
#
# run 'sed' output to 'tee' ... 
#  to modify the file in-situ, and to count the bytes  
  <junk sed -e "s/going //" |tee >(echo -n "$BASHPID " >"$f_pid_size" ;wc -c >>"$f_pid_size") >&3
#
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# The byte-counting process is not a child-process, 
# so 'wait' doesn't work... but wait we must...  
  pid_size=($(cat "$f_pid_size")) ;pid=${pid_size[0]}  
  # $f_pid_size may initially contain only the pid... 
  # get the size when pid termination is assured
  while [[ "$pid" != "" ]] ; do
    if ! kill -0 "$pid" 2>/dev/null; then
       pid=""  # pid has terminated. get the byte count
       pid_size=($(cat "$f_pid_size")) ;size=${pid_size[1]}
    fi
  done
  rm "$f_pid_size"
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#
  exec 3>&- # close fd 3.
  newsize=$(cat newsize)
  echo "# MODIFIED file (before truncating)";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )  cat junk
#
 truncate -s $newsize junk
 echo "# NEW (truncated) file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )  cat junk
#
exit

Вот тестовый вывод

# ORIGINAL file
going abc
going def
# 2 lines, 20 bytes

# MODIFIED file (before truncating)
abc
def
c
going def
# 4 lines, 20 bytes

# NEW (truncated) file
abc
def
# 2 lines, 8 bytes
15
14.05.2013, 05:29
3 ответа

Это зависит полностью от того, как оболочка принимает решение обработать его

bash по умолчанию перезапишет файл истории с локальной историей каждой оболочки, поскольку это выходит, таким образом, последняя оболочка для выхода из побед. histappend опция заставит это добавлять к основной истории вместо этого (shopt -s histappend).

zsh делает то же по умолчанию и имеет несколько опций для контакта с ним:

  • appendhistory - История каждой оболочки добавляется в основной файл истории, поскольку оболочка выходит
  • incappendhistory - Основной файл истории обновляется каждый раз, когда строка выполняется в любой оболочке, вместо того, чтобы ожидать до той оболочки выходы
  • sharehistory - Как incappendhistory, но также и получения по запросу изменяются из основного файла истории во все рабочие оболочки, таким образом, можно выполнить команду в одной оболочке и затем подбросить ударом в другой оболочке и видеть его
11
27.01.2020, 19:50
  • 1
    Теперь скажите мне, как сделать это в Bash ;) –  tante 15.10.2010, 17:07
  • 2
    @tante Делает shopt -s histappend не работают? –  Michael Mrozek♦ 15.10.2010, 17:18

Я первоначально получил эту идею от O'Reilly "книга" Электроинструментов Unix.

В моем .profile Я установил:

export HISTFILE=$HOME/.sh_hist.$$

Каждый раз мой .profile читается, я получаю новый файл истории, названный с PID моей сессии. Если у меня есть несколько логинов, каждый вход в систему получает уникальный файл истории. Работы в ksh и bash.

Если Вы просто открываете новые терминалы на X сессиях, это обычно не оболочки входа в систему, но можно настроить их для действия как оболочки входа в систему. Например, rxvt +ls запустится rxvt как оболочка входа в систему. Проверьте документы на любой терминал, который Вы используете.

Кроме того, если Вы не используете a .logout или .bash_logout файл (или некоторые другие средства) для чистки у Вас в конечном счете будет crapload .sh_hist файлы.

0
27.01.2020, 19:50

tcsh: set savehist = (5000 merge) слияния

0
27.01.2020, 19:50

Теги

Похожие вопросы