zsh + ohmyzsh + powerlevel9k: завершения перестают работать при выдаче 'sudo -s'

305
Drew

У меня странная проблема с zsh и ohmyzsh (с темой powerlevel9k) на MacOS High Sierra.

После установки оммыш при выдаче sudo -sполучаю надоедливый и странный вывод какого-то скрипта. И все доработки перестают работать. Абсолютно такая же конфигурация в Linux работает так же, как и ожидалось.

Вот как это выглядит:

user@host% sudo -s  bracketed-paste-magic () { # undefined builtin autoload -XUz } colors () { emulate -L zsh typeset -Ag color colour color=(00 none 01 bold 02 faint 22 normal 03 standout 23 no-standout 04 underline 24 no-underline 05 blink 25 no-blink 07 reverse 27 no-reverse 08 conceal 28 no-conceal 30 black 40 bg-black 31 red 41 bg-red 32 green 42 bg-green 33 yellow 43 bg-yellow 34 blue 44 bg-blue 35 magenta 45 bg-magenta 36 cyan 46 bg-cyan 37 white 47 bg-white 39 default 49 bg-default) local k for k in ${(k)color} do color[$]=$k done for k in $ do color[fg-$]=$k done color[grey]=$ color[fg-grey]=$ color[bg-grey]=$ colour=(${(kv)color}) local lc=$'\e[' rc=m typeset -Hg reset_color bold_color reset_color="$lc$$rc" bold_color="$lc$$rc" typeset -AHg fg fg_bold fg_no_bold for k in ${(k)color[(I)fg-*]} do fg[$]="$lc$$rc" fg_bold[$]="$lc$;$$rc" fg_no_bold[$]="$lc$;$$rc" done typeset -AHg bg bg_bold bg_no_bold for k in ${(k)color[(I)bg-*]} do bg[$]="$lc$$rc" bg_bold[$]="$lc$;$$rc" bg_no_bold[$]="$lc$;$$rc" done } compdump () { # undefined builtin autoload -XUz } compinit () { emulate -L zsh setopt extendedglob typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1 typeset _i_tag _i_file _i_addfiles _i_fail=ask _i_check=yes _i_name while [[ $# -gt 0 && $1 = -[dDiuC] ]] do case "$1" in (-d) _i_autodump=1 shift if [[ $# -gt 0 && "$1" != -[dfQC] ]] then _i_dumpfile="$1" shift fi ;; (-D) _i_autodump=0 shift ;; (-i) _i_fail=ign shift ;; (-u) _i_fail=use shift ;; (-C) _i_check= shift ;; esac done typeset -gHA _comps _services _patcomps _postpatcomps typeset -gHA _compautos typeset -gHA _lastcomp if [[ -n $_i_dumpfile ]] then typeset -g _comp_dumpfile="$_i_dumpfile" else typeset -g _comp_dumpfile="$/.zcompdump" fi typeset -gHa _comp_options _comp_options=(bareglobqual extendedglob glob multibyte multifuncdef nullglob rcexpandparam unset NO_allexport NO_aliases NO_cshnullglob NO_cshjunkiequotes NO_errexit NO_errreturn NO_globassign NO_globsubst NO_histsubstpattern NO_ignorebraces NO_ignoreclosebraces NO_kshglob NO_ksharrays NO_kshtypeset NO_markdirs NO_octalzeroes NO_posixbuiltins NO_posixidentifiers NO_shwordsplit NO_shglob NO_warnnestedvar NO_warncreateglobal) typeset -gH _comp_setup='local -A _comp_caller_options; _comp_caller_options=(${(kv)options[@]}); setopt localoptions localtraps localpatterns $; local IFS=$'\'\ \\t\\r\\n\\0\''; builtin enable -p \| \~ \( \? \* \[ \< \^ \# 2>&-; exec </dev/null; trap - ZERR; local -a reply; local REPLY; local REPORTTIME; unset REPORTTIME' typeset -ga compprefuncs comppostfuncs compprefuncs=() comppostfuncs=() : $funcstack compdef () { local opt autol type func delete eval new i ret=0 cmd svc local -a match mbegin mend emulate -L zsh setopt extendedglob if (( ! $# )) then print -u2 "$0: I need arguments" return 1 fi while getopts "anpPkKde" opt do case "$opt" in (a) autol=yes ;; (n) new=yes ;; ([pPkK]) if [[ -n "$type" ]] then print -u2 "$0: type already set to $type" return 1 fi if [[ "$opt" = p ]] then type=pattern elif [[ "$opt" = P ]] then type=postpattern elif [[ "$opt" = K ]] then type=widgetkey else type=key fi ;; (d) delete=yes ;; (e) eval=yes ;; esac done shift OPTIND-1 if (( ! $# )) then print -u2 "$0: I need arguments" return 1 fi if [[ -z "$delete" ]] then if [[ -z "$eval" ]] && [[ "$1" = *\=* ]] then while (( $# )) do if [[ "$1" = *\=* ]] then cmd="$" svc="$" func="$_comps[$]" [[ -n $ ]] && svc=$ [[ -z "$func" ]] && func="${$:-$}" if [[ -n "$func" ]] then _comps[$cmd]="$func" _services[$cmd]="$svc" else print -u2 "$0: unknown command or service: $svc" ret=1 fi else print -u2 "$0: invalid argument: $1" ret=1 fi shift done return ret fi func="$1" [[ -n "$autol" ]] && autoload -Uz "$func" shift case "$type" in (widgetkey) while [[ -n $1 ]] do if [[ $# -lt 3 ]] then print -u2 "$0: compdef -K requires <widget> <comp-widget> <key>" return 1 fi [[ $1 = _* ]] || 1="_$1" [[ $2 = .* ]] || 2=".$2" [[ $2 = .menu-select ]] && zmodload -i zsh/complist zle -C "$1" "$2" "$func" if [[ -n $new ]] then bindkey "$3" | IFS=$' \t' read -A opt [[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1" else bindkey "$3" "$1" fi shift 3 done ;; (key) if [[ $# -lt 2 ]] then print -u2 "$0: missing keys" return 1 fi if [[ $1 = .* ]] then [[ $1 = .menu-select ]] && zmodload -i zsh/complist zle -C "$func" "$1" "$func" else [[ $1 = menu-select ]] && zmodload -i zsh/complist zle -C "$func" ".$1" "$func" fi shift for i do if [[ -n $new ]] then bindkey "$i" | IFS=$' \t' read -A opt [[ $opt[-1] = undefined-key ]] || continue fi bindkey "$i" "$func" done ;; (*) while (( $# )) do if [[ "$1" = -N ]] then type=normal elif [[ "$1" = -p ]] then type=pattern elif [[ "$1" = -P ]] then type=postpattern else case "$type" in (pattern) if [[ $1 = (#b)(*)=(*) ]] then _patcomps[$match[1]]="=$match[2]=$func" else _patcomps[$1]="$func" fi ;; (postpattern) if [[ $1 = (#b)(*)=(*) ]] then _postpatcomps[$match[1]]="=$match[2]=$func" else _postpatcomps[$1]="$func" fi ;; (*) if [[ "$1" = *\=* ]] then cmd="$" svc=yes else cmd="$1" svc= fi if [[ -z "$new" || -z "$" ]] then _comps[$cmd]="$func" [[ -n "$svc" ]] && _services[$cmd]="$" fi ;; esac fi shift done ;; esac else case "$type" in (pattern) unset "_patcomps[$^@]" ;; (postpattern) unset "_postpatcomps[$^@]" ;; (key) print -u2 "$0: cannot restore key bindings" return 1 ;; (*) unset "_comps[$^@]" ;; esac fi } typeset _i_wdirs _i_wfiles _i_wdirs=() _i_wfiles=() autoload -Uz compaudit if [[ -n "$_i_check" ]] then typeset _i_q if ! eval compaudit then if [[ -n "$_i_q" ]] then if [[ "$_i_fail" = ask ]] then if ! read -q "?zsh compinit: insecure $_i_q, run compaudit for list. Ignore insecure $_i_q and continue [y] or abort compinit [n]? " then print -u2 "$0: initialization aborted" unfunction compinit compdef unset _comp_dumpfile _comp_secure compprefuncs comppostfuncs _comps _patcomps _postpatcomps _compautos _lastcomp return 1 fi _i_wfiles=() _i_wdirs=() else (( $#_i_wfiles )) && _i_files=("${(@)_i_files:#(${(j:|:)_i_wfiles%.zwc})}") (( $#_i_wdirs )) && _i_files=("${(@)_i_files:#(${(j:|:)_i_wdirs%.zwc})/*}") fi fi typeset -g _comp_secure=yes fi fi autoload -Uz compdump compinstall _i_done='' if [[ -f "$_comp_dumpfile" ]] then if [[ -n "$_i_check" ]] then IFS=$' \t' read -rA _i_line < "$_comp_dumpfile" if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files && $ZSH_VERSION = $_i_line[4] ]] then builtin . "$_comp_dumpfile" _i_done=yes fi else builtin . "$_comp_dumpfile" _i_done=yes fi fi if [[ -z "$_i_done" ]] then typeset -A _i_test for _i_dir in $fpath do [[ $_i_dir = . ]] && continue (( $_i_wdirs[(I)$_i_dir] )) && continue for _i_file in $_i_dir/^([^_]*|*~|*.zwc)(N) do _i_name="$" (( $+_i_test[$_i_name] + $_i_wfiles[(I)$_i_file] )) && continue _i_test[$_i_name]=yes IFS=$' \t' read -rA _i_line < $_i_file _i_tag=$_i_line[1] shift _i_line case $_i_tag in (\#compdef) if [[ $_i_line[1] = -[pPkK](n|) ]] then compdef $na "$" "${(@)_i_line[2,-1]}" else compdef -na "$" "$" fi ;; (\#autoload) autoload -Uz "$_i_line[@]" $ [[ "$_i_line" != \ # ]] && _compautos[$]="$_i_line" ;; esac done done if [[ $_i_autodump = 1 ]] then compdump fi fi for _i_line in complete-word delete-char-or-list expand-or-complete expand-or-complete-prefix list-choices menu-complete menu-expand-or-complete reverse-menu-complete do zle -C $_i_line .$_i_line _main_complete done zle -la menu-select && zle -C menu-select .menu-select _main_complete bindkey '^i' | IFS=$' \t' read -A _i_line if [[ $ = expand-or-complete ]] && zstyle -a ':completion:' completer _i_line && (( $ <= ${#_i_line} )) then bindkey '^i' complete-word fi unfunction compinit compaudit autoload -Uz compinit compaudit return 0 } compinstall () { # undefined builtin autoload -XUz } down-line-or-beginning-search () { # undefined builtin autoload -XU } edit-command-line () { # undefined builtin autoload -XU } is-at-least () { emulate -L zsh local IFS=".-" min_cnt=0 ver_cnt=0 part min_ver version order min_ver=(${=1}) version=(${=2:-$ZSH_VERSION} 0) while (( $min_cnt <= ${#min_ver} )) do while [[ "$part" != <-> ]] do (( ++ver_cnt > ${#version} )) && return 0 if [[ $ = *[0-9][^0-9]* ]] then order=($ $) if [[ $ = <->* ]] then [[ $order != ${${(On)order}} ]] && return 1 else [[ $order != ${${(O)order}} ]] && return 1 fi [[ $order[1] != $order[2] ]] && return 0 fi part=$ done while true do (( ++min_cnt > ${#min_ver} )) && return 0 [[ $ = <-> ]] && break done (( part > min_ver[min_cnt] )) && return 0 (( part < min_ver[min_cnt] )) && return 1 part='' done } up-line-or-beginning-search () { # undefined builtin autoload -XU } url-quote-magic () { # undefined builtin autoload -XUz }  root@host# echo $SHELL zsh  root@host# 

Есть идеи, почему это могло произойти? Я знаю, что sudo -sперезаписывает все переменные среды, но не думаю, что это может быть проблемой.

Env Vars:

root@host# echo $SHELL zhs  root@host# dscl . -read $HOME UserShell UserShell: /bin/zsh 

То же самое для обычного пользователя.

1
`sudo -s` запускает новую оболочку от имени пользователя * root *. Это также означает, что оболочка получит свою конфигурацию от * root *. Поскольку вы получаете «раздражающий и странный вывод какого-либо скрипта», я бы предположил, что конфигурация * root'а * `zsh` нарушена. Это также может быть `bash`, если оболочкой входа вашего текущего пользователя не является` zsh`. Не могли бы вы отредактировать ваш вопрос, чтобы он содержал данные, о которых идет речь, а также выходные данные `echo $ SHELL` и` dscl. -читать $ HOME UserShell`? Adaephon 5 лет назад 0
содержание вывода уже в вопросе, пожалуйста, прочитайте внимательно. Я добавил результаты двух других команд для обычного пользователя и root Drew 5 лет назад 0
Извини за это. Я пропустил начальное приглашение оболочки и предположил, что это ваша конфигурация. Adaephon 5 лет назад 0

1 ответ на вопрос

0
Adaephon

Основная проблема заключается в том, что root имеет другую конфигурацию zsh, чем у вашего пользователя. поскольку вместо вызывающего пользователя sudo -sиспользуется конфигурация целевого пользователя ( root ), вы получаете другую конфигурацию zsh.

Выходные данные выглядят так, как будто они могут быть получены из functionsвстроенного (или, typeset -fили declare -f, что эквивалентно), которое, кажется, вызывается в одном из скриптов конфигурации root :

/root/.zshrc /root/.zshenv /root/.zprofile /root/.zlogin 

Если все, что вы хотите сделать, это предоставить root ту же конфигурацию zsh, что и у вашего обычного пользователя, вы можете просто скопировать ее:

  1. войдите как root, напримерsudo -s
  2. удалите любые файлы конфигурации zsh, которые могут иметь root

    mkdir ~/zsh-old-conf mv ~/.zshrc ~/.zshenv ~/.zprofile ~/.zlogin ~/.oh-my-zsh ~/zsh-old-conf 
  3. скопируйте вашу конфигурацию обычных пользователей в дом root :

    cp -r /Users/REGULAR/.zshrc /Users/REGULAR/.oh-my-zsh ~/ 
  4. Проверьте, работает ли сейчас конфигурация. Чтобы сохранить данные, оставьте текущий сеанс открытым и войдите в систему как root с другого терминала. Таким образом, вы можете отменить изменения, если конфигурация по какой-то причине не работает.

Я так и думал, прежде чем создать эту проблему ... Проблема в том, что это автоматическая настройка ANSI .. Конфигурация абсолютно идентична для пользователя root и пользователя без полномочий root. Поэтому шансы, что это решение могло помочь, были очень низкими ... Я попробовал это сейчас, и это не помогло. Drew 5 лет назад 0
Фактически, при выполнении `sudo -s` переменная` $ HOME` по-прежнему показывает домашний каталог пользователя без полномочий root, поэтому я могу даже удалить все файлы, связанные с `.zsh *` и `oh-my-zhs`, из `/ var / root /` и до сих пор видим, как работает zsh + ohmyzsh, при запуске совершенно новой оболочки и выполнении там `sudo -s` ... Но вывод все еще сохраняется .. Drew 5 лет назад 0
Это странно. Признаюсь, я не тестировал это на Mac, но похоже, что `sudo -s` работает на Mac иначе, чем на Linux, так как для меня` $ HOME` сбрасывается в `/ root`. Вы можете попробовать `sudo -i`? Он похож на `-s`, но пытается имитировать начальный вход в систему, сбрасывать переменные окружения в пользовательские настройки по умолчанию, читать конфигурацию и т. Д. Adaephon 5 лет назад 0
Я могу рассказать вам больше .. Когда я сделал все это, пользователь root на моем Mac был отключен .. Это глупая функция macos, поэтому невозможно войти в систему как root, но если вы не пользователь root с правами администратора, вам разрешено делать `sudo -s`, хотя обычный` su` не будет работать и вернет простую строку `Sorry` Drew 5 лет назад 0
С технической точки зрения, в этом случае пользователь root по-прежнему использует конфигурацию zsh / oh-my-zsh пользователя без полномочий root ... Так что я подумал, может быть, это только из-за этого ... Но даже после включения "традиционного" пользователя sudo это все тот же... Drew 5 лет назад 0
Странно, что с `sudo -i` мой` $ SHELL` это `/ bin / sh`, хотя я вручную изменил его на` root: *: 0: 0: Системный администратор: / var / root: / usr / local / bin / zsh` в моем `/ etc / passwd` Drew 5 лет назад 0
Вполне возможно, что MacOS не заботится (что больше не нужно?), Что вы установили в `/ etc / passwd`. Обратите внимание, что постоянные пользователи даже не перечислены там. Если я правильно понимаю man-страницу (и если она действительно описывает, что на самом деле происходит), возможно, вы получите сеанс `/ bin / sh` вместо` zsh` при запуске `sudo -s` или` sudo -i` , Вы можете попробовать `sudo -i zsh -l`. Единственное, о чем я могу думать, - это * не * запускать сеансы оболочки как root, а intead просто запускает `sudo COMMAND` всякий раз, когда вам нужны повышенные разрешения. Мне кажется, что Apple действительно не хочет, чтобы пользователи входили в систему как root. Adaephon 5 лет назад 0
это интересно, но когда я сделал `sudo -i zsh -l`, это сработало как положено ... почему ???? Drew 5 лет назад 0
Без команды `sudo -i` сам решает, какую оболочку запустить. А на MacOS это выглядит как `/ bin / sh`. Явно передав в качестве аргумента `zsh -l`, вы заставляете` sudo` запускать `zsh`. `-l` говорит` zsh` запускаться как * login shell *, поэтому он читает все вышеупомянутые файлы конфигурации. Также может быть возможно пропустить это или заменить его на `-i` (для * интерактивной оболочки *), тогда он будет читать только из` .zshrc` и `.zshenv`. Adaephon 5 лет назад 0
Хорошо, когда я делаю `sudo -i` - я действительно получаю / bin / sh. Когда делаю `sudo -i zsh` - тогда я получаю / usr / local / bin / zsh с тем странным выводом, который есть в OP. И только когда я говорю sudo использовать zsh в качестве * login shell *: `sudo -i zsh -l`, я получаю нормальное ожидаемое поведение. У вас есть идеи, как это объяснить? Drew 5 лет назад 0
Ой, подождите !!! Я попробовал это еще пару раз, и теперь я получаю этот вывод даже с `sudo -i zsh -l` ... Это просто безумие! Я так растерялся. Drew 5 лет назад 0
Нашли других людей с той же проблемой и без решения: https://stackoverflow.com/questions/41182414/oh-my-zsh-completion-not-working Drew 5 лет назад 0

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