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

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

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

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

  • Игнорировать файлы для завершения zsh для SVN
  • Расширение {a..d} до abcd в zsh
  • Как определить функцию, которая обрабатывает `command not found`?
  • Настройка экрана, проблем с окном
  • Каковы эти строки% (...) в файле jail.conf fail2ban и как они работают?
  • zsh завершение - показать больше параметров, чем просто псевдоним
  •  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 , они не вызовут никаких проблем. Почему они только поднимают ошибки из этой привязки ключа.

  • Как я могу применить `cut` к нескольким файлам, а затем« вставить »результаты?
  • Таинственное повторение введенной команды в оболочке
  • В чем главная проблема, с которой сталкивается кто-то, мигрирующий из bash в zsh?
  • Что такое расщепление слов? Почему это важно в программировании оболочки?
  • zsh эквивалент bash show-all-if-twoiguous?
  • «Команда не найдена», когда функция sudo'ing от ~ / .zshrc
  • 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 - лучшая ОС в мире.