Script em modo root

Pessoal, trabalho em uma instituição aqui onde moro e ela resolveu disponibilizar máquinas com Linux (Ubuntu 20.04) pra acesso do povo em geral onde só acessa quem tem um cadastro e é tudo de graça.
Bom, eé aí que começa a aventura. É um total de 40 máquinas pra gerenciar através do Epoptes e o maior problema é ter que atualizar o sistema, pois os computadores não ficam conectados a internet o tempo todo, somente quando o usuário vai usar o computador.
Então eu resolvi criar um script em Python usando subprocess pra gerenciar essa tarefa onde o programa, através de um laço de repetição vai procurar conexão com a internet e assim que qualquer usuário se conectar a internet, o programa vai rodar os comandos pra atualizar os repositórios e aplicativos do sistema.
A questão é que esse tipo de tarefa requer senha root. Se eu colocar o script pra iniciar junto com o sistema direto do diretório /etc/init.d, ele vai funcionar ou vai ser inútil por precisar de senha? Porque essa tarefa tem que rodar em segundo plano e sem precisar inserir senha de root. Como faço isso? Alguém tem uma sugestão? Afinal, fazer essa tarefa, na mão, em 40 máquinas é meio chato e por isso eu estou querendo automatizar.
Eu consegui fazer isso pra apagar os arquivos que os usuários deixam nos diretórios do Home das máquinas em hora marcada. Isso foi fácil porque não requer senha de root, mas essa outra tarefa apareceu essa dúvida.
Agradeço a ajuda.

Não sei do /etc/init.d (tenho a impressão que essa interface está obsoleta em versões mais novas do Ubuntu), mas um serviço do systemd vai sim conseguir rodar como root sem intervenção do usuário.

Porém, acho que você está duplicando a função do pacote unattended-upgrades do Ubuntu, e provavelmente os sysadmins do fórum vão citar algum “framework” mais adequado para uniformizar as máquinas.

1 curtida

No Lubuntu 16.04 tinha a opção de usar o arquivo “/etc/rc.local” coloca os outros usuários para visualizar mas permita que semente o root possa alterá-lo e coloque ele na propriedade do root para segurança contra alteração não autorizada.
Não testei no Ubuntu 20.04 se esse arquivo ainda existe mas no Lubuntu 20.04 ele não existe então ele deve ser criado a estrutura dele é assim:

#!/bin/bash
# Coloque o que quiser aqui antes do exite.
exite 0

Sim é um script Bash se precisar faça curso de Bash no youtube.
Eu não testei no 20.04 mas ainda deve funcionar.
Esse script é executado como root na inicialização.
Colocar partes sensíveis de atualização do sistema é arriscado porque se a atualização parar no meio do processo o sistema pode quebrar.
O apt update e upgrade é seguro.

2 curtidas

O jeito simples de resolver é vc criar o script de atualização e colocar para rodar como tarefa agendada. Em várias distribuições, mesmo com o systemD tendo essa possiblidade, há grandes possibilidades que algum pacote que fornece o crontab esteja instalado. Daí é só seguir tutorial de configurar tarefas no crontab (que tem desde os primórdios da internet) para rodar o script com permissões de root em horários programados/intervalo de tempo.

Essa não é a maneira elegante de fazer, mas deve funcionar se vc está cuidando de um número reduzido de máquinas.

3 curtidas

Eu acho que o Ansible pode ser útil no seu caso. Explico:

Remotamente, do PC principal, você poderia executar o playbook que iria atualizar os PCs, sem a intervenção do usuário ou senha de root. Tudo através de troca de chaves SSH.

Você poderia também definir por grupo de hosts/individual e ir atualizando a medida que for percebendo que alguém tem usado o PC.

Um ponto a ressaltar é que tanto o modo que planejou, quanto esse que cito acima, vai causar problemas de desempenho (a exceção se estão equipados com SSD) quando o usuário estiver com o PC em uso e necessitar atualizar algo. Seria interessante programar via cron ou via Ansible playbook, para atualização uma vez por dia pelo menos (antes das atividades). Ou uma vez por semana.

2 curtidas

Eu me enganei quando escrevi e coloquei o /etc/init.d, eu estou usando o systemd, na verdade. O /etc/init.d funcionou, mas não como eu gostaria e por isso eu mudei pro systemd.

Esse diretório, realmente, não existe no Ubuntu 20.04 e a questão é que eu estou usando Python pra automatização com uns comandos shell. Ainda não tenho tanto entendimento sobre shell script pra criar um programa todo dessa forma.

marcar o script como ‘suid’ seria uma solução? ou desnecessário?

A questão de fazer como tarefa agendada é que eu não sei a qual momento alguém vai usar uma determinada máquina e daí fica um pouco complicado agendar e por isso tenho que fazer dessa forma. Até mesmo porque o laço de repetição que eu vou usar é só pra saber se tem conexão com a internet e depois que encontrou, ele atualiza e acaba a tarefa. Ficaria, mais ou menos assim no Python:

while not conexao:
    comando pra buscar conexao
else:
    atualiza tudo.

Essa é a questão: como, na maioria das vezes, eu estou ocupado com outras coisas no ambiente de trabalho, vou acabar esquecendo de fazer isso e automatizando direto do sistema das máquinas clientes fica muito mais prático

Infelizmente, não tem outro jeito. Em uma situação como essa, no máximo, eu poderia agendar pra fazer essa tarefa de dois ou três em três dias pra não deixar algumusuário irritado com a lentidão da internet ou do sistema. E, realmente, as máquinas vão perder um pouco de performance porque os computadores, apesar de serem relativamente novos, usam HD.
Mas valeu pelas dicas, pessoal. A minha dúvida jáfoi sanada e agora eu játenho uma ideia de como resolver isso.

Não pó você vai chamar o seu programa python pelo script bash mas você não precisa trocar a linguagem.
E eu passei como vc criá-lo.

1 curtida

Ah! Entendi agora. É dessa forma que eu estou fazendo. O script em Python, eu coloquei dentro do diretório /opt/Program. Valeu, pela ajuda.

Haveria a possibilidade de reabrir esse tópico? Pois, apesar de ter pesquisado e tentado usar várias formas de fazer o script funcionar como root no sistema, ainda não consegui fazer funcionar.

:wave:t2:

Como se fosse o acabamento, será que se tentar configurar o script no sudoers como ALL poderia funcionar? Seria mais ou menos assim:

usuário ALL(root) NOPASSWD: /caminho/do/script.

:vulcan_salute:t2:

2 curtidas

Mas nesse caso não seria perigoso pois qualquer usuário fazer o que bem quisesse até mesmo com os arquivos do sistema? Eu quero fazer de uma forma que não permita que outros possam mexer nos arquivos do sistema.

Tem este detalhe…
Eu ainda não fiz um teste mas eu acredito que só daria permissão para os usuários se não especificarmos o /caminho/do/script no final.
Mas teria de fazer um teste para ver. Ou se o pessoal souber de algo para complementar :blush:

1 curtida

Não se o arquivo do script tiver as devidas permissões (dono e grupo root, modo 700).

Essa instrução do sudo autoriza apenas o arquivo do script a ser rodado sem senha, mas se o usuário tentar dar um sudo rm -rf /* ou seja mais o que for não vai ser autorizado. Se o arquivo não for editável por qualquer um (configurando os modos), está razoavelmente seguro.

De qualquer jeito, é bom ver se não é o script que não está conseguindo root, mas sim a funcionalidade dele que não está pegando sem intervenção do usuário (como, por exemplo, tentar ler um entrada de “sim ou não” e o script falhar por estar rodando no “fundão” do sistema).

3 curtidas

Entendo. Nesse caso, o script tem apenas comandos pra atualização dos repositórios e aplicativos.
Os comandos seriam esses:

sudo rm /var/cache/apt/archives/lock && sudo rm /var/lib/dpkg/lock-frontend && sudo rm -rf /var/lib/apt/lists/* && sudo apt update && sudo apt full-upgrade -y && sudo apt dist-upgrade -y && sudo apt install -f && sudo apt autoremove -y && sudo apt autoclean -y

E as máquinas estão todas com instalação mínima do Ubuntu 20.04 pra não correr o risco de ter algo interativo durante a instalação/atualização de algum pacote, apesar disso não ser uma garantia.

Durante os testes em máquina virtual eu tentei gerar uma saída usando o tee no comando e ficou assim:

sudo rm /var/cache/apt/archives/lock && sudo rm /var/lib/dpkg/lock-frontend && sudo rm -rf /var/lib/apt/lists/* && sudo apt update && sudo apt full-upgrade -y && sudo apt dist-upgrade -y && sudo apt install -f && sudo apt autoremove -y && sudo apt autoclean -y |& tee -a /home/acmm_ubuntu20/Documentos/install_log.txt

Mas nem gerou nada como saída.

O tee, da maneira que está aí, só vai enviar a saída do último comando (apt autoclean) para o arquivo de log, e as dezenas de && só permitem executar um comando caso todos os anteriores sejam bem sucedidos, logo é provável que algum dos comandos anteriores tenha falhado.

Vale lembrar que, no systemd, não é preciso esse truque do tee: a saída de tudo que é rodada como serviço do sistema é enviada para o journald e pode ser analisada com o journalctl. Com isso, deve ser possível analisar onde houve a falha. Aposto que sejam os dois primeiros rms, que falham caso o arquivo não exista.

2 curtidas

Realmente, faz sentido e eu não tinha atentado pra isso. Vou colocar os comandos em linhas separadas.

Dessa eu não sabia. Se bem que eu criei essa forma de saída só pra saber o que estava acontecendo na hora do teste mesmo. Na versão final isso vai sair.
Eu vou fazer mais testes aqui e depois dou um retorno. Valeu a dica.

O shell é nervoso pra aprender… Cheio de trique-trique. Faz o script o mais simples possível.

Tipo, pra que remover o lock? Imagina que a atualização começou com um usuário, daí outro veio, logou no sistema e vc remove a trava e inicia outro processo de instalação. Altas chances de dar problemas dos difíceis de resolver.

Procura mais informações sobre o já citado unattended-upgradespra evitar maiores problemas tentando reinventar a roda:
https://help.ubuntu.com/community/AutomaticSecurityUpdates

4 curtidas