Как проверить, если текущая оболочка zsh уже выполнила команды `dircolors` и` stty`?

Я использую zsh версии 5.3.1:

 % zsh --version zsh 5.3.1 (x86_64-pc-linux-gnu) 

Я пытаюсь определить привязку ключа, используя последовательность ключей Cx r , чтобы перезагрузить конфигурацию zsh . Благодаря @Gilles , я включил этот код в свой ~/.zshrc :

 reread_zshrc () { . ~/.zshrc } zle -N reread_zshrc bindkey '^Xr' reread_zshrc 

Он работает, за исключением того, что когда я нажимаю Cx r , zsh жалуется на ошибки:

 stty: 'standard input': Bad file descriptor stty: 'standard input': Bad file descriptor dircolors: /home/user/.dircolors: Bad file descriptor 

Я могу воспроизвести эти ошибки со следующим минимальным zshrc :

 stty -ixon stty quit undef eval "$(dircolors -b ~/.dircolors)" reread_zshrc () { . ~/.zshrc } zle -N reread_zshrc bindkey '^Xr' reread_zshrc 

Вот почему я включил 2 stty команды и команду dircolors в моем zshrc .

stty -ixon позволяет драйверу терминала интерпретировать Cs и Cq как управление потоком терминала: по умолчанию Cs замораживает терминал и Cq размораживает его. Он позволяет использовать Cs и Cq в Cq клавиш для оболочки или текстового редактора, не замораживая терминал.

stty quit undef позволяет драйверу терминала отправлять сигнал SIGQUIT при нажатии SIGQUIT C-\ . Опять же, он позволяет использовать этот ключ в привязке клавиш без завершения процесса переднего плана.

eval "$(dircolors -b ~/.dircolors)" просит команду ls прочитать ее конфигурацию из ~/.dircolors . Он позволяет настраивать цвета на выходе команды ls .

Полагаю, мне нужно защитить эти 3 строки от повторного получения zsh если они уже были выполнены в текущей оболочке. Но я не знаю, какое условие писать:

 if <stty and dircolors haven't been executed already>; then stty -ixon stty quit undef eval "$(dircolors -b ~/.dircolors)" if 

Кроме того, я хотел бы лучше понять эти сообщения об ошибках, потому что, если я их zsh в интерактивной оболочке zsh , они не вызовут никаких проблем. Почему они только поднимают ошибки из этой привязки ключа.

  • Автоматическое отображение меню завершения по типу
  • Отобразить имя китайской машины в командной строке
  • Что есть? "^ [B" backward-word "При попытке настроить ZSH?
  • Zsh завершает составление рецептов
  • Автозаполнение оболочки очень медленное после форматирования частичного диска
  • Синтаксис команды повторения в zsh
  • Автозаполнение ZSH
  • Предотвращение использования zsh от использования псевдонимов в CWD (подсказка)
  • One Solution collect form web for “Как проверить, если текущая оболочка zsh уже выполнила команды `dircolors` и` stty`?”

    В zle виджетах, похоже, zsh закрывает stdin. Я предполагаю, что zsh хочет, чтобы команды в этих виджетах не вмешивались непосредственно в пользовательский ввод, но было бы разумнее перенаправить stdin из / dev / null ( это будет исправлено в следующей версии ).

    Когда stdin (дескриптор файла 0) закрыт, это означает, что первый файл, который открывает команда, становится его stdin (поскольку файловые дескрипторы выделены из первого свободного).

    В dircolors это вызывает ошибку. dircolors открывает ваш ~/.dircolors , а затем пытается сделать его своим stdin, не заметив, что это уже был его stdin (потому что это возвращает fd open() ). Таким образом, dup2(0,0) (dup stdin на себя) терпит неудачу с ошибкой EBADF, о которой сообщает dircolors .

    stty устанавливает настройки терминала на его stdin. Здесь stdin закрыт, поэтому stty возвращается с ошибкой.

    Здесь вы можете изменить свой виджет, чтобы он восстанавливал stdin на терминал:

     reread_zshrc () . ~/.zshrc < $TTY 

    Но обратите внимание, что изменение настроек tty из виджета zle (хотя я не знаю, что делает ваша команда stty ) – это плохая идея, так как zle устанавливает tty в специальный режим для редактирования строк, который вы не хотите испортить с (и в конце редактирования нормальные настройки tty будут восстановлены в любом случае, так что сделанные вами изменения будут потеряны).

    Так что, возможно, вместо этого вы должны сделать stdin /dev/null (так как вы действительно не хотите делать что-то с терминалом там), но stty все равно будет жаловаться (поскольку /dev/null не является устройством tty), так что вы можете также хотите перенаправить stderr в / dev / null, чтобы скрыть эти сообщения об ошибках (хотя это скроет все сообщения об ошибках):

     reread_zshrc() . ~/.zshrc < /dev/null 2> /dev/null 
    Linux и Unix - лучшая ОС в мире.