bash não autocomplete meu comando ao usar o sudo?

6

Estou usando o SaltStack. Eu gostaria de completar automaticamente o nome do minion ao chamar o comando salt .

A seguinte linha foi adicionada ao ~/.bashrc :

complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt

Em seguida, digite salt inTabsalt integration-Tab ; Eu posso ver que funciona como esperado:

$ salt integration-TabTab
integration-c   integration-u   integration-u2

Para usar com sudo , adicionei complete -cf sudo em ~/.bashrc , mas não funcionou:

sudo salt inTab

não retornou nada.

Eu também tentei instalar bash_completion e adicionei as seguintes linhas a ~/.bash_profile :

if [ -f $(brew --prefix)/etc/bash_completion ]; then
    . $(brew --prefix)/etc/bash_completion
fi

mas sem sorte.

Eu senti falta de algo?

Atualizar

Ah, a primeira coisa que eu gostaria de dizer é que às vezes funciona:

$ sudo salt integration-TabTab
integration-c   integration-u   integration-u2

e às vezes não.

So first, let's see how much your bash_completion package does.

Como posso verificar isso? Aqui está minha função:

# a wrapper method for the next one, when the offset is unknown
_command()
{
    local offset i

    # find actual offset, as position of the first non-option
    offset=1
    for (( i=1; i <= COMP_CWORD; i++ )); do
        if [[ "${COMP_WORDS[i]}" != -* ]]; then
            offset=$i
            break
        fi
    done
    _command_offset $offset
}

# A meta-command completion function for commands like sudo(8), which need to
# first complete on a command, then complete according to that command's own
# completion definition - currently not quite foolproof (e.g. mount and umount
# don't work properly), but still quite useful.
#
_command_offset()
{
    local cur func cline cspec noglob cmd i char_offset word_offset \
        _COMMAND_FUNC _COMMAND_FUNC_ARGS

    word_offset=$1

    # rewrite current completion context before invoking
    # actual command completion

    # find new first word position, then
    # rewrite COMP_LINE and adjust COMP_POINT
    local first_word=${COMP_WORDS[$word_offset]}
    for (( i=0; i <= ${#COMP_LINE}; i++ )); do
        if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
            char_offset=$i
            break
        fi
    done
    COMP_LINE=${COMP_LINE:$char_offset}
    COMP_POINT=$(( COMP_POINT - $char_offset ))

    # shift COMP_WORDS elements and adjust COMP_CWORD
    for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
        COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
    done
    for (( i; i <= COMP_CWORD; i++ )); do
        unset COMP_WORDS[i];
    done
    COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

    COMPREPLY=()
    _get_comp_words_by_ref cur

    if [[ $COMP_CWORD -eq 0 ]]; then
        _compopt_o_filenames
        COMPREPLY=( $( compgen -c -- "$cur" ) )
    else
        cmd=${COMP_WORDS[0]}
        if complete -p ${cmd##*/} &>/dev/null; then
            cspec=$( complete -p ${cmd##*/} )
            if [ "${cspec#* -F }" != "$cspec" ]; then
                # complete -F <function>

                # get function name
                func=${cspec#*-F }
                func=${func%% *}

                if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
                    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
                else
                    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
                fi

                # remove any \: generated by a command that doesn't
                # default to filenames or dirnames (e.g. sudo chown)
                # FIXME: I'm pretty sure this does not work!
                if [ "${cspec#*-o }" != "$cspec" ]; then
                    cspec=${cspec#*-o }
                    cspec=${cspec%% *}
                    if [[ "$cspec" != @(dir|file)names ]]; then
                        COMPREPLY=("${COMPREPLY[@]//\\:/:}")
                    else
                        _compopt_o_filenames
                    fi
                fi
            elif [ -n "$cspec" ]; then
                cspec=${cspec#complete};
                cspec=${cspec%%${cmd##*/}};
                COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
            fi
        elif [ ${#COMPREPLY[@]} -eq 0 ]; then
            _filedir
        fi
    fi
}

if you type sudo mkdirTabTab, does it show a list of directories?

Sim:

$ sudo mkdir TabTab
.FontForge/        .djangopypi2/      .ievms/            .ssh/              .wireshark-etc/
    
por quanta 07.07.2014 / 10:58

3 respostas

1

Resposta rápida:

Suponho que você use MacOSX com brew .

Tente:

brew update
brew install bash-completion
brew info bash-completion
# bash-completion: stable 1.3
. $(brew --prefix)/etc/bash_completion
complete -p sudo

Você deve ver algo assim:

complete -F _root_command sudo

Teste:

function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
complete -F _comp_foo foo

Digite foo Espaço Guia Guia
Você deve ver a b c

Digite sudo foo Espaço Guia Guia
Você deve ver a b c

Em seguida, remova complete -fc sudo dos seus arquivos de inicialização ( ~/.bash_profile , ~/.bashrc etc)
Adicione as seguintes linhas aos seus arquivos de inicialização:

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion
fi

# Your compspec here
complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt

Reabra o terminal.
Digite complete -p sudo .
Você deve ver complete -F _root_command sudo .

Digite complete -p salt .
Você deveria ver algo assim:

complete -o default -o nospace -W 'a
b
c' salt

bash-completion2. * note :
Você pode instalar o bash-completion2 : link
Mas:

  • 2.* funciona com Bash 4.*
  • 2.* usa a opção -D para o carregamento lento de compspecs. Então, complete -p sudo outputs complete: sudo: no completion specification até que você digite sudo Espaço Tab
por 27.06.2015 / 10:14
1

Verifique set -o para ver se o modo posix está ativado. Em caso afirmativo, desative com set +o posix

No modo "posix", a conclusão da tabulação do bash é por algum motivo desabilitada no modo "vi". Eu não vi nenhuma explicação porque esse comportamento é assim, nem porque é específico para o modo vi, então eu não me incomodei em explicar.

PS: Essa resposta é mais adequada para alguém que se depara com a pergunta por meio de um mecanismo de pesquisa ... não para sua configuração específica.

Atualizar :
Chet Ramey diz :

in POSIX mode, the vi editing mode should not map tab to complete. This is because POSIX.2 completely specifies the behavior of the vi editing mode, and the standard requires tab to be mapped to self insert by default.

    
por 13.05.2015 / 02:02
-1

sudo não fornece um shell de login, a menos que você peça -i . Assim, você descobrirá que, sem isso, você precisará carregar as conclusões do sistema:

. /etc/bash_completion

Se você executar com -i , $HOME será ~root e, portanto, nada escrito ao usuário ~/.bashrc não será lido. Se você puder separar o material de conclusão do restante de seu ~/.bashrc , fonte com . e isso deve funcionar.

    
por 04.05.2015 / 20:40