can you still recover if all three functions are marked readonly?
Sim, normalmente você pode, embora isso não signifique que você deva.
Assim como você pode anular as variáveis somente leitura anexando um depurador e chamando unbind_variable
, como mostrado na resposta do anishsane a essa pergunta , você também pode cancelar funções readonly passando seus nomes para unbind_func
usando um depurador .
Esta não é uma abordagem razoável quando eles não são apenas de leitura (se é que realmente é). Nessa situação, você deve usar a solução do cuonglm , que aproveita como unset
é tratado no POSIX mode. Essa solução é algo que você pode usar na vida real.
Como não há garantias reais de que seu shell se comportará de maneira razoável depois de contornar readonly
com um depurador, sugiro evitá-lo sempre que quiser uma alternativa mais razoável, como desistir e reiniciar seu shell ou substituir seu shell por um novo usando exec
, está disponível.
Com isso dito, aqui está o método do anishsane adaptado para desfazer funções em vez de uma variável:
cat <<EOF | sudo gdb
attach $$
call unbind_func("unset")
call unbind_func("builtin")
call unbind_func("command")
detach
EOF
Observe que $$
está expandido no ID do processo do shell, porque nenhuma parte de EOF
em <<EOF
é citada.
Eu testei isso no Bash 4.3.48 (1) -release no Ubuntu 16.04 LTS, e funcionou. Você precisa de gdb
para isso, embora possa ser adaptado para outros depuradores. Como anishsane comentou , a canalização de cat
tem como objetivo evitar um deadlock em que o processo que fornece entrada para gdb
é aquele que gdb
parou. Acredito que alcança esse objetivo, porque em um pipeline de dois ou mais comandos, Bash executa cada comando em uma subcamada. Mas não tenho certeza se é o caminho mais robusto. Em última análise, no entanto, não há nenhuma garantia real de que isso funcione de qualquer maneira, já que é totalmente razoável que o Bash assuma as variáveis de leitura e as funções não mudem. Na prática, meu palpite é que isso praticamente sempre funciona.
Para usar essa técnica como escrita, você precisa de sudo
instalado e precisa poder sudo
para raiz. Você pode, naturalmente, substituí-lo por outro método de elevação de privilégio. Dependendo de qual sistema operacional você está executando e como está configurado, você poderá omitir sudo
e executar gdb
como você mesmo, em vez de como root. Por exemplo, o kernel do Linux irá consultar o valor de /proc/sys/kernel/yama/ptrace_scope
, que você pode fazer. definir através sysctl e pode ler ou (como root) escrever, para determinar quais processos podem depurar outros processos. Se o valor for 1
, somente o pai direto de um processo - ou qualquer processo executado como raiz - poderá depurá-lo. Os sistemas GNU / Linux mais recentes definiram como 1
, e é por isso que incluí sudo
.
Essa descrição do comportamento do kernel do Linux é um pouco simplificada, em que outros valores de ptrace_scope
são permitidos e em que a relação requerida por 1
pode ser ajustada. Consulte a documentação relevante para obter detalhes completos.