Iniciando um script como outro usuário

10

Eu criei um script em /etc/init.d/ que tem que executar vários outros scripts de outros usuários (não-root privilegiados) de seus diretórios home, como se eles tivessem começado.

Eu inicio esses scripts com: sudo -b -u <username> <script_of_a_particular_user>

E isso funciona. Mas para cada script de usuário que continua em execução (por exemplo, algum watchdog), vejo um processo sudo pai correspondente, ainda ativo e em execução como root. Isso cria uma bagunça na lista de processos ativos.

Então, minha pergunta é: Como posso iniciar (bifurcar) outro script do script bash existente como outro usuário e deixá-lo como um processo órfão (autônomo)?

Explicação mais detalhada:
Eu estou basicamente tentando fornecer a outros usuários na máquina um meio de executar coisas no início do sistema ou no desligamento do sistema, executando arquivos executáveis encontrados nos respectivos subdiretórios encontrados em seu diretório inicial, chamado .startUp e .shutDown. Desde que eu não encontrei nenhum outro meio para fazer isso eu escrevi meu script bash que faz exatamente isso e eu configurei como um script de serviço (seguindo o exemplo de esqueleto) em /etc/init.d/ assim quando é executado com o argumento start, ele inicia tudo a partir dos diretórios .startUp e, quando executado com o argumento stop, ele inicia tudo de diretórios .shutDown de todos os usuários como eles.

Alternativamente, também estou interessado se eu pudesse ter usado alguma solução existente para resolver este problema.

UPDATE
Eu olhei em volta um pouco e encontrei esta pergunta: link

Aceito resposta lá, para usar: sudo -u user sh -c "daemon & disown %1" , funciona para mim. Mas eu também tentei sem disown% 1 e é o mesmo. Então é isso que funciona para mim como eu esperava:

sudo -u <username> bash -c "<script_of_a_particular_user> &"

Minha pergunta adicional agora é: por que está funcionando sem renúncia? ainda devo deixar a chamada disown , independentemente, para algum caso especial em potencial?

UPDATE 2

Aparentemente, isso também funciona:

su <username> -c "<script_of_a_particular_user> &"

Existe alguma diferença entre esta chamada e a chamada sudo? Eu sei que isso é potencialmente uma questão totalmente diferente. Mas desde que eu estou encontrando as respostas aqui eu mesmo, talvez por causa deste tópico alguém poderia esclarecer isso aqui.

UPDATE 3
Ambos os métodos com su ou sudo agora produzem um novo processo startpar (processo único que é executado como root) após eu inicializar a máquina. Visível na lista de processos como:

startpar -f -- <name_of_my_init.d_script>

Por que esse processo é gerado? Obviamente, estou fazendo algo errado, já que nenhum outro script init.d tem esse processo em execução.

UPDATE 4
O problema com o startpar é resolvido. Eu comecei outra pergunta para isso:
processo startpar deixado pendurado ao iniciar processos de rc.local ou init.d

E outra pergunta para discutir mais sobre o lançamento de mecanismos para usuários não privilegiados:
Fornece aos usuários normais (não-raiz) recursos de inicialização automática e desligamento automático

    
por Ivan Kovacevic 31.03.2014 / 23:56

4 respostas

15

A resposta correta para isso foi que para "daemonização" adequada, entrada padrão, saída padrão e erro padrão precisam ser redirecionados para / dev / null (ou algum arquivo real):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"

su - substitua a identidade do usuário pelo argumento someuser
-c - su para executar o comando especificado
nohup - Execute um comando imune a restrições. Para evitar casos em que o processo pai terminará o processo filho. Adicionado aqui apenas no caso. Mas na verdade não tem efeito no meu caso particular. Se é necessário depende do ambiente (verifique shopt )
> / dev / null - Reduza a saída padrão para nada, basicamente desabilitando-a.
< strong> 2 > & 1 - Redirecionar erro padrão (2) saída para a saída padrão (1), que é redirecionada para null
& - desanexar para o plano de fundo. redireciona a entrada padrão também para / dev / null.

Isto é essencialmente exatamente o que o utilitário start-stop-daemon do Debian dpkg faz em seu núcleo. É por isso que prefiro iniciar scripts dessa maneira, em vez de introduzir outra chamada de utilitário externo no meu código. O start-stop-daemon é útil nos casos em que você possui programas daemon completos que você precisa iniciar e onde você precisa de funcionalidades adicionais que o start-stop-daemon fornece ( por exemplo, verificar se o processo especificado já está sendo executado para que não seja iniciado novamente).

Também é importante notar que você também pode fechar os descritores de arquivo do seu processo em vez de redirecioná-los para / dev / null , por exemplo:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 < & - Fecha a entrada padrão (0)
1 > & - Fecha a saída padrão (1)
2 > & - Fecha a saída do erro padrão (2)

A direção de < > sinais não importa, pois o número descritor de arquivo longo é especificado. Então, isso é igualmente bom:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

ou

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

No entanto, há uma maneira um pouco mais curta de escrever isso, sem números para stdin e stdout, onde a direção importa:

su someuser -c "some_script.sh <&- >&- 2>&- &" 

Quando os descritores de arquivo são fechados ou redirecionados para / dev / null (o start-stop-daemon está fazendo o redirecionamento para / dev / null), o processo é seguro para ser executado em segundo plano como um daemon. Então, isso é o que é necessário para evitar problemas ( startpar ) com o lançamento de scripts durante o tempo de inicialização.

Implementei toda a solução da minha ideia inicial e a coloquei no GitHub: link

    
por 02.04.2014 / 02:52
3

Você pode usar o start-stop-daemon fora do init.d com a opção --user .

    
por 01.04.2014 / 03:23
2

Eu não testei totalmente isso, mas acho que algo como:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

na inicialização e, em seguida,

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

ao desligar.

O manuseio do script .shutDown pode ser feito por algo como a coisa de inicialização, mas você não pode ter certeza de que os scripts vão rodar para terminar, já que o desligamento deve acontecer de qualquer maneira: -)

deve fazer o truque, talvez você deva inserir algum redirecionamento de entrada, mas então você teria que se preocupar com arquivos de log sendo preenchidos.

    
por 02.04.2014 / 14:02
1

Você já tentou usar su ?

su -c /home/user/.startUp/executable - user

-c diz ao su para executar o comando, e o último parâmetro é o usuário para executá-lo como.

    
por 01.04.2014 / 00:53