AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-96893

mesr's questions

Martin Hope
mesr
Asked: 2025-04-27 02:34:42 +0800 CST

Maneira recomendada de remover o pacote virtual 'nodejs-legacy' no servidor Debian headless

  • 5

Estou atualizando o NodeJS e o NPM para a versão LTS mais recente no meu antigo servidor Debian 11 (bullseye). Limpei os pacotes e dependências nodejs e npm originais da distribuição e instalei com sucesso o NodeJS v22.15.0 e o NPM v10.9.2 usando o nodesource .

Agora estou tentando remover o pacote nodejs-legacy que — presumo — provavelmente não é mais necessário, mas tanto o apt quanto o apt-get (eles se comportam exatamente da mesma forma nesse aspecto) reclamam que:

$ sudo apt remove nodejs-legacy
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Virtual packages like 'nodejs-legacy' can't be removed
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Pelo que entendi, pacotes virtuais apenas definem dependências e/ou instalam arquivos de configuração. Por que um pacote, mesmo "virtual" — ou como quiserem chamá-lo — não pode ser desinstalado? O apt (ou apt-get ) não pode simplesmente atualizar o banco de dados de pacotes e/ou remover esses arquivos?

Este pacote em particular nem sequer faz parte de nenhuma dependência:

$ sudo apt depends nodejs-legacy
<nodejs-legacy>
$ sudo apt rdepends nodejs-legacy
<nodejs-legacy>

Acho que posso simplesmente deixar assim, já que não parece entrar em conflito com mais nada (pelo menos até agora). Mas prefiro manter meus servidores livres de lixo velho espalhado por aí.

Qual é a maneira recomendada de livrar um sistema Debian de pacotes virtuais antigos que não são mais necessários?

debian
  • 1 respostas
  • 11 Views
Martin Hope
mesr
Asked: 2024-02-26 11:50:07 +0800 CST

Estranha inconsistência entre a execução e o fornecimento do script Bash

  • 8

Sei que este não é um título muito descritivo (sugestões são bem-vindas), mas o fato é que estou mexendo nos cabelos há horas e não tenho ideia de onde possa estar a raiz do problema.

Escrevi um script Bash simples para bate-papo CLI entre pares em uma rede local:

#!/usr/bin/env bash

# Usage: ./lanchat <local_ip>:<local_port> <remote_ip>:<remote_port>

# set -x
set -o errexit -o nounset -o pipefail

IFS=':' read -a socket <<< "$1"
LOCAL_IP=${socket[0]}
LOCAL_PORT=${socket[1]}

IFS=':' read -a socket <<< "$2"
REMOTE_IP=${socket[0]}
REMOTE_PORT=${socket[1]}

RECV_FIFO=".tmp.lanchat"

trap "rm '$RECV_FIFO'; kill 0" EXIT

mkfifo "$RECV_FIFO"

while true; do nc -n -l -q 0 -s "$LOCAL_IP" -p "$LOCAL_PORT" > "$RECV_FIFO"; done &

TMUX_TOP="while true; do cat '$RECV_FIFO'; done"
TMUX_BOTTOM="while IFS= read -r line; do nc -n -q 0 '$REMOTE_IP' '$REMOTE_PORT' <<< \$line; done"

tmux new "$TMUX_TOP" \; split -v "$TMUX_BOTTOM"

A máquina no IP 172.16.0.2 é um VPS rodando Debian 11, e em 172.16.0.100 está meu computador local rodando Arch.

Ao executar os comandos manualmente no prompt em ambos os lados, obtenho o resultado desejado, que confirma que não há problema com a comunicação da rede e que a lógica do script está correta.

## VPS (Debian) side as follows; exchange IPs for local (Arch) side.
$ mkfifo .tmp.lanchat
$ while true; do nc -n -l -q 0 -s 172.16.0.2 -p 1234 > .tmp.lanchat; done &
$ tmux new "while true; do cat .tmp.lanchat; done" \; split -v "while IFS= read -r line; do nc -n -q 0 172.16.0.100 1234 <<< \$line; done"
## Test communication in both directions: all right; then CTRL-C twice to exit both tmux panels
$ kill %1; rm .tmp.lanchat

quando executo ambos os lados como um script, porém, apenas o lado local (Arch) imprime mensagens do servidor (Debian). O servidor não imprime nada do meu computador local. Quando rastreio a execução com set -x, tudo em ambos os lados se parece exatamente com os comandos que insiro manualmente, com os valores corretos no lugar das variáveis.

Agora, o estranho é que se eu executar o script no lado do Arch e os comandos no prompt (como acima) no lado do Debian, tudo funcionará bem novamente. Além disso, se eu executar o script no lado do Arch, mas fornecê -lo no lado do Debian, isso também funcionará bem.

Adicionar saída detalhada a ambas as chamadas nc no lado do Arch até imprime Connection to 172.16.0.2 1234 port [tcp/*] succeeded!. No entanto, adicionar a tee log.txtà chamada para nc no modo de escuta no lado Debian não captura nada:

#...
while true; do
    nc -n -l -q 0 -s "$LOCAL_IP" -p "$LOCAL_PORT" | tee log.txt > "$RECV_FIFO";
done &
#...

Tentei estabelecer a conexão em todas as ordens possíveis entre os dois pares. Até reiniciei o servidor e minha máquina local para ter certeza de que não havia instâncias órfãs ou zumbis de nc abraçando o soquete que de alguma forma escapou da detecção.

Agora, o Debian e o Arch executam versões diferentes do nc . Então, aparentemente, parece que essa poderia ser uma explicação possível. Mas o fato de obter o script do lado do Debian funcionar bem não exclui essa possibilidade?

O que diabos está acontecendo aqui?

bash
  • 1 respostas
  • 93 Views
Martin Hope
mesr
Asked: 2022-11-18 07:41:03 +0800 CST

Redirecionando stderr para fd temporário em um script Bash

  • 5

Vejo que muitas perguntas foram feitas e respondidas no SE sobre redirecionamentos no Bash usando exec , mas nenhuma parece responder à minha pergunta.

O que estou tentando realizar é redirecionar toda a saída para stderr em um script para um fd temporário e restaurá-lo de volta para stderr apenas em caso de encerramento malsucedido do script. A capacidade de restaurar o conteúdo de stderr é necessária em caso de encerramento malsucedido, para retornar ao chamador informações sobre o erro. Redirecionar stderr para /dev/nuldescartaria tanto o ruído irrelevante quanto as informações úteis. Tanto quanto possível, arquivos temporários explícitos devem ser evitados, pois eles adicionam vários outros problemas (consulte https://dev.to/philgibbs/avoiding-temporary-files-in-shell-scripts ). O conteúdo de stdoutdevem ser retornados de forma transparente para o chamador. Ele será ignorado em caso de encerramento sem sucesso do script, mas o script não precisa se preocupar com isso.

A razão para fazer isso é que o script é chamado de outro programa que considera qualquer saída para stderr um erro, em vez de testar um código de saída diferente de zero. No exemplo abaixo, openssl envia um indicador de progresso para stderr que deve ser ignorado após a conclusão bem-sucedida.

Abaixo está uma versão simplificada do meu script (observe que o openssl aqui é apenas um espaço reservado para instruções arbitrárias e possivelmente mais complexas):

#!/bin/bash
set -euo pipefail

# Redirect stderr to temp fd 3
exec 3>&2

# In case of error, copy contents of fd 3 to stderr
trap 'cat <&3 >&2' ERR

# Upon exit, restore original stderr and close fd 3
trap 'exec 2>&3 3>&-' EXIT

# This nonetheless outputs the progress indicator to stderr
openssl genpkey -algorithm RSA

Mas obviamente estou perdendo algo, pois o script continua imprimindo o conteúdo de stderr após o término bem-sucedido, mas agora bloqueia em caso de falha. Acho que estou confuso sobre como os redirecionamentos com exec funcionam. O que estou errando?

bash
  • 1 respostas
  • 41 Views
Martin Hope
mesr
Asked: 2022-07-11 05:27:27 +0800 CST

Por que o sudo nem sempre gera um subprocesso do shell?

  • 7

Estou tentando entender por que alguns shells parecem receber um tratamento especial quando chamados com sudo . Por exemplo, parece haver dois comportamentos possíveis:

O grupo "implícito" ( pstree é um filho direto de sudo , sem shell entre):

$ sudo pstree -s $$
systemd───login───bash───sudo───pstree
$ sudo bash -c 'pstree -s $$'
systemd───login───bash───sudo───pstree
$ sudo zsh -c 'pstree -s $$'
systemd───login───bash───sudo───pstree
$ sudo dash -c 'pstree -s $$'
systemd───login───bash───sudo───pstree

O grupo "explícito" (o shell é um filho direto de sudo ):

$ sudo ksh -c 'pstree -s $$'
systemd───login───bash───sudo───ksh───pstree
$ sudo tcsh -c 'pstree -s $$'
systemd───login───bash───sudo───tcsh───pstree
$ sudo fish -c 'pstree -s $fish_pid'
systemd───login───bash───sudo───fish───pstree

Obviamente, parece haver algum tipo de integração acontecendo entre o sudo e alguns shells, mas não encontrei documentação sobre isso. Eu também pesquisei o código-fonte do sudo e do bash , mas também não consegui encontrar nenhuma pista.

Esta outra questão parece relacionada: Por que (...) não gera um novo processo filho quando executado em segundo plano?

Minhas versões de sudo e bash são:

$ sudo --version
Sudo version 1.8.29
...
$ bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
...
bash zsh
  • 1 respostas
  • 1131 Views
Martin Hope
mesr
Asked: 2022-06-21 06:59:47 +0800 CST

Por que o executável é encontrado sem um caminho completo, apesar de sua localização não estar no caminho de pesquisa?

  • 3

Esta questão é sobre entender o(s) motivo(s) por trás de uma inconsistência percebida entre o comportamento documentado e o real ao chamar um executável por meio de sudo . Quando a opção secure_path está habilitada (padrão no meu sistema), o caminho de pesquisa se comporta conforme o esperado. Mas quando a opção está desabilitada, algo estranho acontece: um executável em /usr/local/binpode ser alcançado sem um nome de caminho totalmente qualificado, apesar de sua localização não estar no caminho de pesquisa.

Informação do sistema

O seguinte software está atualmente instalado no meu sistema:

## Yeah... still haven't migrated to Alma
[me@localhost ~]$ cat /etc/centos-release
CentOS Linux release 8.5.2111

[me@localhost ~]$ bash --version | head -1
GNU bash, version 4.4.20(1)-release (x86_64-redhat-linux-gnu)

[me@localhost ~]$ sudo --version
Sudo version 1.8.29
Sudoers policy plugin version 1.8.29
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.29

[me@localhost ~]$ ssh -V
OpenSSH_8.0p1, OpenSSL 1.1.1k  FIPS 25 Mar 2021

O PAM não define ou atualiza o valor da variável PATH no meu sistema:

[me@localhost ~]$ grep --recursive 'pam_env\.so' /etc/pam.d
/etc/pam.d/fingerprint-auth:auth        required      pam_env.so
/etc/pam.d/smartcard-auth:auth        required      pam_env.so
/etc/pam.d/su:auth        required    pam_env.so
/etc/pam.d/password-auth:auth        required      pam_env.so
/etc/pam.d/system-auth:auth        required      pam_env.so

[me@localhost ~]$ sudo cat /etc/security/pam_env.conf /etc/environment | grep PATH
# be useful to be set: NNTPSERVER, LESS, PATH, PAGER, MANPAGER .....
#PATH       DEFAULT=${HOME}/bin:/usr/local/bin:/bin\

Meu /etc/sudoersarquivo define um valor secure_path para todos os sudoers:

[me@localhost ~]$ sudo grep --recursive secure_path /etc/sudoers /etc/sudoers.d
/etc/sudoers:Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

O padrão do Bash é o seguinte valor PATH:

[me@localhost ~]$ env --ignore-environment bash -c 'echo $PATH'
/usr/local/bin:/usr/bin

Por fim, estou conectado ao sistema através do SSH, cujo /etc/ssh/sshd_configarquivo contém esta linha:

[me@localhost ~]$ sudo grep PATH /etc/sshd_config
# This sshd was compiled with PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

Procedimento de replicação

Para replicar, primeiro crio um script fictício e o instalo em /usr/local/bin:

[me@localhost ~]$ cat > dummy <<EOF
#!/usr/bin/bash
echo 'Found!'
EOF

[me@localhost ~]$ sudo install --owner=root --group=root --mode=755 dummy /usr/local/bin

Verifico se o caminho de pesquisa funciona conforme o esperado quando não estiver usando sudo :

## The /usr/local/bin location is part of my search path
[me@localhost ~]$ echo $PATH
/home/me/.local/bin:/home/me/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin

## This is expected
[me@localhost ~]$ dummy
Found!

E usando sudo , nenhuma surpresa aqui também:

## Sudo's secure_path value
[me@localhost ~]$ sudo --user=other env | grep PATH
PATH=/usr/bin:/bin:/usr/sbin:/sbin

## This is expected
[me@localhost ~]$ sudo --user=other which dummy
which: no dummy in (/sbin:/bin:/usr/sbin:/usr/bin)

## This too, of course
[me@localhost ~]$ sudo --user=other dummy
sudo: dummy: command not found

## Indeed, a fully qualified path name is required
[me@localhost ~]$ sudo --user=other /usr/local/bin/dummy
Found!

Então, desabilito secure_path (cuidado aqui! o uso do visudo é recomendado), seja comentando a linha /etc/sudoersou criando um arquivo /etc/sudoers.d/localcom as seguintes linhas:

# Disable secure_path if set
Defaults !secure_path

Isso deve impedir que sudo , quando chamado com o --preserve-envswitch, substitua a variável de ambiente PATH pelo valor de secure_path . E funciona como esperado.

No entanto, ao não usar o --preserve-envswitch e não solicitar uma sequência de login completa com o --loginswitch (assim, não fornecendo nenhum dos arquivos de inicialização do Bash) e sem atribuição ao PATH em nenhum dos arquivos do ambiente PAM, algo estranho acontece:

## Not sure where this PATH value is from, neither from sudo's secure_path option
## (not set), PAM environment files (contain no assignment to PATH), Bash startup
## scripts (not sourced), nor Bash or sshd default PATH values (no match).
[me@localhost ~]$ sudo --user=other env | grep PATH
PATH=/usr/bin:/bin:/usr/sbin:/sbin

## Regardless, this is expected
[me@localhost ~]$ sudo --user=other which dummy
which: no dummy in (/usr/bin:/bin:/usr/sbin:/sbin)

## But wait! What?!?
[me@localhost ~]$ sudo --user=other dummy
Found!

Então, como é que se which dummyqueixa de dummy não estar no caminho de pesquisa enquanto uma chamada direta para dummysem prefixo de caminho o encontra?

Documentação relevante

A seguir estão as referências a várias informações que achei relevantes ao pesquisar essa questão.

A documentação do Sudo diz isso sobre a opção secure_path :

Caminho usado para cada comando executado a partir do sudo. Se você não confia nas pessoas que executam o sudo para ter uma variável de ambiente PATH sã, você pode querer usar isso. Outro uso é se você quiser que o “caminho raiz” seja separado do “caminho do usuário”. Os usuários do grupo especificado pela opção isent_group não são afetados pelo secure_path. Esta opção não é definida por padrão.

De acordo com a documentação do pam_env nas páginas do manual, apenas o /etc/environment, o /etc/security/pam_env.confe ~/.pam_environmentdeve ser processado pelo módulo pam_env por padrão, a menos que nomes de arquivo não padrão sejam especificados. Este não é o caso no meu sistema e nenhum desses arquivos define ou atualiza o valor de PATH.

A página man do Bash diz:

PATH O caminho de pesquisa para comandos. É uma lista de diretórios separados por dois pontos nos quais o shell procura por comandos (consulte EXECUÇÃO DE COMANDO abaixo). Um nome de diretório de comprimento zero (nulo) no valor de PATH indica o diretório atual. Um nome de diretório nulo pode aparecer como dois dois-pontos adjacentes ou como dois-pontos iniciais ou finais. O caminho padrão depende do sistema e é definido pelo administrador que instala o bash. Um valor comum é “/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin”.

Esta página da documentação do Bash no gnu.org ( https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html ) explica quando os vários arquivos de inicialização são originados. Na minha demonstração acima, nenhum desses arquivos deve ser originado, pois não estou gerando novos shells em --loginor --interactive, nem chamando sudo com o --loginswitch.

Esta resposta do ServerFault ( https://serverfault.com/questions/833762/where-does-the-bash-path-on-centos-7-get-usr-local-bin-from#answer-838552 ) explica os valores padrão do Bash para a variável PATH. Mesmo que tenha sido respondido para o Bash no CentOS 7, a resposta ainda é relevante para a versão do Bash empacotada com o CentOS 8. De acordo com a resposta aceita, a fonte do bash config-top.htem o seguinte:

/* The default value of the PATH variable. */
#ifndef DEFAULT_PATH_VALUE
#define DEFAULT_PATH_VALUE \
  "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:."
#endif

/* The value for PATH when invoking `command -p'.  This is only used when
   the Posix.2 confstr () function, or CS_PATH define are not present. */
#ifndef STANDARD_UTILS_PATH
#define STANDARD_UTILS_PATH \
  "/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc"
#endif
bash sudo
  • 1 respostas
  • 92 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve