shell script comando exec [RESOLVIDO]

1. shell script comando exec [RESOLVIDO]

Taffarel
xikara

(usa Outra)

Enviado em 10/11/2014 - 21:08h

Gostaria de saber como eu faso o comando abaixo.Da seguinte forma eu tenho que dar dois comando
junta as informações em um. Esse comando e so um exemplo vou colocar mais coisa dentro do while


#!/bin/bash
var=$(ls)
aux=$(ls /home)
exec 3< $var$aux
while read linha <&3; do
echo "$linha"
done
exec 3<&-


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/11/2014 - 11:52h

daemonio escreveu:

A sintaxe do exec é:

exec descritor <|> arquivo


Na verdade, é um pouco mais do que isso.

Normalmente, quando você diz ao shell para rodar algum comando externo (sem usar exec), ele cria um processo novo e executa o comando nesse processo novo, e fica esperando o processo novo acabar. Você pode aplicar redirecionamentos de entrada e saída sobre esses comandos, mas eles só vão valer nos processos criados pelo shell, não no processo original do próprio shell.

Uma pipeline é uma extensão da ideia acima. Cada comando que constitui a pipeline executa num processo distinto, tanto entre si quanto do processo do shell. Entre tais processos, o shell faz um tipo especial de redirecionamento, que é tal que a saída de cada comando é redirecionado para a entrada do comando seguinte na pipeline.

É possível redirecionar também alguns comandos internos do shell, tanto de/para arquivos quanto como parte de uma pipeline. No entanto, o redirecionamento vale somente para esse comando, e qualquer comando subsequente não vai ter noção da existência dos redirecionamentos dos comandos anterior. Aliás, no caso específico de pipelines, se o comando interno vier à direta do sinal de pipe (“|”), o shell vai executar tal comando num processo filho, o que torna o caráter transitório desse redirecionamento uma necessidade, não uma escolha.

Sabendo disso, podemos voltar ao comando exec.

O exec serve para executar um comando externo sem criar um novo processo (i.e. o comando toma completamente o lugar do shell -- quando o comando termina, o processo termina). O exec permite, mas não obriga, que se façam redirecionamentos de entrada e saída sobre o processo corrente antes de executar o comando externo, de modo que o comando começa a executar com todos os redirecionamentos já aplicados.

Não é possível executar um comando interno do shell com exec. No entanto, é possível omitir completamente a referência a qualquer comando. Esse é um caso particular de uso, em que a mesma instância do shell continua executando no mesmo processo, como se nada tivesse acontecido, exceto pelo fato de que qualquer redirecionamento aplicado pelo exec ao processo adquire caráter permanente no próprio shell. Qualquer comando executado posteriormente, tanto interno como externo, mesmo em processos filhos, vai enxergar tais redirecionamentos.

É até possível

exemplos são:


exec 4</etc/passwd
exec 5>/tmp/arquivo_escrita


resumindo: a última parte deve ser um nome de arquivo (ou um número de descritor associado a algum arquivo)

No seu código, você utilizou a saída dos comandos como parâmetro pro exec e isso não vai dar certo.

O correto seria:


exec < <(ls)


O <(ls) cria um arquivo interno e o nome dele é passado para o exec pelo bash.


Na verdade, existe uma outra forma de “corrigir” o que ele fez.

exec 3<<< "$var$aux" 


Só que eu não sei o quanto isso impacta no uso de memória.

O exec é util quando se quer ler vários arquivos com um so while loop. É necessário ser um arquivo em disco já que ele trabalha com descritores de arquivos.


Errado. Apesar da terminologia, descritores de arquivo não são necessariamente arquivos em disco. Sockets e pipes, por exemplo, são descritores de arquivos, e não são visíveis em parte alguma do sistema de arquivos. Aliás, mesmo algumas coisas visíveis no sistema de arquivos e que podem produzir descritores quando abertas com open() são totalmente virtuais, e não residem realmente em disco (várias coisas em /dev, /proc e /sys, por exemplo).

Aliás, o exemplo que você mesmo deu quando fez “exec < <(ls)” mostra isso: você está associando ao descritor 0 um pseudo-arquivo que é um pipe feito com a saída do comando ls.

Para juntar somente saídas de vários comandos, tem-se métodos mais simples, como esse:


$ (cmd1; cmd2; cmd3) > saida_de_todos_comandos.txt


ou por que não:


$ cmd1 > saida_de_todos_comandos.txt
$ cmd2 >> saida_de_todos_comandos.txt
$ cmd3 >> saida_de_todos_comandos.txt


depois só processar o arquivo txt em um só while loop.


A vantagem de fazer com arquivo intermediário é que você minimiza a quantidade de processos simultaneamente em execução. Isso é útil se você tiver sérias restrições de memória ou limites impostos no número de processos. Mas há motivos por que não:

- Porque pode não ser desejável -- às vezes, nem mesmo possível -- criar um arquivo temporário (disco cheio, disco read-only).
- O espaço em disco pode acabar durante a escrita do arquivo.
- Você pode ter limites de tamanho máximo de arquivo aplicados ao processo; para pipes, não.
- Porque o arquivo pode ser apagado/renomeado/truncado/modificado entre um comando gerador e outro (segundo exemplo).
- Porque o arquivo pode ser apagado/renomeado/truncado/modificado antes que o comando de leitura tenha a chance de começar a consumir dados.

É possível fazer a mesma coisa com redirecionamento em /dev/fd e/ou /proc.

exec 3< <(cmd1; cmd2; cmd3)

while read var <&3; do
...
done

exec 3<&-


3. Re: shell script comando exec [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 10/11/2014 - 21:52h

Não seria mau se você tentasse caprichar um pouco mais no Português.

Você deveria ler um pouco mais sobre redirecionamento de entrada e saída. A manpage do Bash é bem detalhada nesse assunto.

Aliás, está óbvio que você está com dúvidas também sobre uso de variáveis e outros aspectos de uso e de sintaxe do shell. Tanta coisa, que provavelmente seria melhor se você usasse um livro ou tutorial, em vez de tirar dúvidas só aqui. Um estudo mais focado e orientado.


4. help

Taffarel
xikara

(usa Outra)

Enviado em 10/11/2014 - 22:04h

E já consegui fazer algums Plugins para nagios. So que agora estou fazendo um novo plugin do jeito que vc me passou em outro post. Aquele eu já resolvi. Eu sei que tenho que estudar muito mas o tempo e curto.Pois eu tenho prazo para entregar isso pronto


5. Re: shell script comando exec [RESOLVIDO]

Marcos Paulo Ferreira
daemonio

(usa Slackware)

Enviado em 11/11/2014 - 17:56h

A sintaxe do exec é:

exec descritor <|> arquivo

exemplos são:


exec 4</etc/passwd
exec 5>/tmp/arquivo_escrita


resumindo: a última parte deve ser um nome de arquivo (ou um número de descritor associado a algum arquivo)

No seu código, você utilizou a saída dos comandos como parâmetro pro exec e isso não vai dar certo.

O correto seria:


exec < <(ls)


O <(ls) cria um arquivo interno e o nome dele é passado para o exec pelo bash.

O exec é util quando se quer ler vários arquivos com um so while loop. É necessário ser um arquivo em disco já que ele trabalha com descritores de arquivos.

Para juntar somente saídas de vários comandos, tem-se métodos mais simples, como esse:


$ (cmd1; cmd2; cmd3) > saida_de_todos_comandos.txt


ou por que não:


$ cmd1 > saida_de_todos_comandos.txt
$ cmd2 >> saida_de_todos_comandos.txt
$ cmd3 >> saida_de_todos_comandos.txt


depois só processar o arquivo txt em um só while loop.



t+


6. Re: shell script comando exec [RESOLVIDO]

Marcos Paulo Ferreira
daemonio

(usa Slackware)

Enviado em 12/11/2014 - 17:33h

paulo1205 escreveu:

daemonio escreveu:

A sintaxe do exec é:

exec descritor <|> arquivo


Na verdade, é um pouco mais do que isso.

Normalmente, quando você diz ao shell para rodar algum comando externo (sem usar exec), ele cria um processo novo e executa o comando nesse processo novo, e fica esperando o processo novo acabar. Você pode aplicar redirecionamentos de entrada e saída sobre esses comandos, mas eles só vão valer nos processos criados pelo shell, não no processo original do próprio shell.

Uma pipeline é uma extensão da ideia acima. Cada comando que constitui a pipeline executa num processo distinto, tanto entre si quanto do processo do shell. Entre tais processos, o shell faz um tipo especial de redirecionamento, que é tal que a saída de cada comando é redirecionado para a entrada do comando seguinte na pipeline.

É possível redirecionar também alguns comandos internos do shell, tanto de/para arquivos quanto como parte de uma pipeline. No entanto, o redirecionamento vale somente para esse comando, e qualquer comando subsequente não vai ter noção da existência dos redirecionamentos dos comandos anterior. Aliás, no caso específico de pipelines, se o comando interno vier à direta do sinal de pipe (“|”), o shell vai executar tal comando num processo filho, o que torna o caráter transitório desse redirecionamento uma necessidade, não uma escolha.

Sabendo disso, podemos voltar ao comando exec.



Sim, é muito além do que postei. Não estava tentando dar um tutorial sobre exec, somente focar na parte de redirecionamento de arquivos, daí postei a sintaxe referente a isso, exec + entrada/saida + nome de arquivo. Além disso, pela própria postagem do OP, é possível ver que existe outra sintaxe que nem recebe nome de arquivo, que é no fechamento do descritor associado: exec <&3-.


O exec serve para executar um comando externo sem criar um novo processo (i.e. o comando toma completamente o lugar do shell -- quando o comando termina, o processo termina). O exec permite, mas não obriga, que se façam redirecionamentos de entrada e saída sobre o processo corrente antes de executar o comando externo, de modo que o comando começa a executar com todos os redirecionamentos já aplicados.


O exec também executa um comando externo em cima do processo atual, sem a necessidade de se criar um novo. Não citei esse comportamento porque vai muito além do que o OP necessita. Não era objetivo postar uma resposta completa sobre o comando, tudo que ele faz, sintaxes completas e outras trivialidades. A ideia era focar somente na dúvida do autor: ler mais de uma saída ao mesmo tempo.



Na verdade, existe uma outra forma de “corrigir” o que ele fez.

exec 3<<< "$var$aux" 


Só que eu não sei o quanto isso impacta no uso de memória.


Anotado. Não sabia da sintaxe com here-strings.



O exec é util quando se quer ler vários arquivos com um so while loop. É necessário ser um arquivo em disco já que ele trabalha com descritores de arquivos.


Errado. Apesar da terminologia, descritores de arquivo não são necessariamente arquivos em disco. Sockets e pipes, por exemplo, são descritores de arquivos, e não são visíveis em parte alguma do sistema de arquivos. Aliás, mesmo algumas coisas visíveis no sistema de arquivos e que podem produzir descritores quando abertas com open() são totalmente virtuais, e não residem realmente em disco (várias coisas em /dev, /proc e /sys, por exemplo).

Aliás, o exemplo que você mesmo deu quando fez “exec < <(ls)” mostra isso: você está associando ao descritor 0 um pseudo-arquivo que é um pipe feito com a saída do comando ls.


Realmente errei ao falar que "É necessário ser um arquivo em disco". Não precisa estar em disco, pode estar virtualmente no kernel. Meu próprio exemplo demonstrava esse fato. Sua explicação foi perfeita. Porém, a primeira argumentação continua correta que é a possibilidade de ler vários arquivos em um loop.


A vantagem de fazer com arquivo intermediário é que você minimiza a quantidade de processos simultaneamente em execução. Isso é útil se você tiver sérias restrições de memória ou limites impostos no número de processos. Mas há motivos por que não:

- Porque pode não ser desejável -- às vezes, nem mesmo possível -- criar um arquivo temporário (disco cheio, disco read-only).
- O espaço em disco pode acabar durante a escrita do arquivo.
- Você pode ter limites de tamanho máximo de arquivo aplicados ao processo; para pipes, não.
- Porque o arquivo pode ser apagado/renomeado/truncado/modificado entre um comando gerador e outro (segundo exemplo).
- Porque o arquivo pode ser apagado/renomeado/truncado/modificado antes que o comando de leitura tenha a chance de começar a consumir dados.


Cabe ao OP decidir qual a melhor resposta. Somente postei as alternativas, sem avaliar questões de restrições e/ou desempenho entre elas.


exec 3< <(cmd1; cmd2; cmd3)

while read var <&3; do
...
done

exec 3<&-



Essa pode ser também uma solução do problema.

tl;dr
1) exec permite redirecionar arquivos descritores associados à arquivos no disco ou virtualmente no kernel.
2) exec permite executar um comando externo dentro do processo do script, sobrescrevendo-o.
3) exec aceita here-string: exec 3<<<"string"
4) existem várias soluções, usando exec ou não, que dependem das necessidades do OP.





7. não deu certo

Taffarel
xikara

(usa Outra)

Enviado em 16/11/2014 - 21:35h

Desculpe minha ignorância mais nada que eu fiz deu certo.Eu usei o eclipse para shell e só dava erro.
Eu não quero usar nenhum arquivo esterno.Eu quero e dar comandos e pegar a resposta pra depois aplicar as regras
como o exemplo abaixo(($(ls /home);$(ls /boot);$(ls /bin);)) nada de txt ou coisa similar não precisa usar o exec também pode ser qualquer outra coisa que junta tudo e processa dentro de um while

exec 3< <($(ls /home);$(ls /boot);$(ls /bin);)

while read var <&3; do
echo $var
done

exec 3<&-


exec 3< <((ls /home);(ls /boot);(ls /bin);)

while read var <&3; do
echo $var
done

exec 3<&-


exec 3< <(ls /home;ls /boot;ls /bin;)

while read var <&3; do
echo $var
done

exec 3<&-



exec 3< <(`ls /home`;`ls /boot`;`ls /bin`;)

while read var <&3; do
echo $var
done

exec 3<&-




8. mensagem de erro eclipse

Taffarel
xikara

(usa Outra)

Enviado em 17/11/2014 - 09:42h

Erro de sintaxe: o redirecionamento inesperado


9. Re: shell script comando exec [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/11/2014 - 10:38h

O que você quer dizer com "eclipse para shell"?

O uso implícito de named pipes (nas formas “<(comando_gerador_de_dados)” e “>(comando_consumidor_de_dados)”) funcionam no Korn Shell (ksh) e Bourne-Again Shell (bash), mas não funcionam no Bourne Shell original (sh) e seus clones (ash, dash etc.).

Então, cuidado: no RedHat e derivados (Fedora, CentOS etc.), o /bin/sh é um link para /bin/bash, mas sistemas Debian e derivados (Ubuntu, Mint etc.) têm /bin/sh totalmente distinto do /bin/bash, sendo o primeiro derivado do dash e mais leve, usado para scripts simples, ao passo que o segundo, por ser bem mais pesado, é usado principalmente como shell de login e bem poucos scripts mais elaborados (scripts mais elaborados mesmo geralmente usam Python ou Perl).


10. obrigago

Taffarel
xikara

(usa Outra)

Enviado em 17/11/2014 - 13:43h

Tem um plugin no eclipse ele interpreta depura comando shell script todos os script que eu estou fazendo e no eclipse

foi a partir desse link que eu descobrir que o eclipse roda shell script
http://www.vivaolinux.com.br/dica/Shell-Script-no-Eclipse-It-is-possible

vão ver se dar certo no servidor
ehehheheh
exec 3< <($comando1;$comando2;$comando3;$comando4;$comando5;$comando6;$comando7;$comando8;$comando9;$comando10;$comando11)
while read var <&3; do

frequencia=$(echo $var | awk '{print $6}')
canal=$(echo $var | awk '{print $3}')
operadora=$(echo $var | awk '{print $4}')
if [ ${#frequencia} -ne 0 ]; then
if [ "${frequencia#-0}" -lt 20 ]; then
aux="Canal:"$canal" - Operadora:"$operadora" - Frequencia:"$frequencia
echo $aux
fi
fi
done

if [ "${#aux}" -eq 0 ]; then
echo "OK" && exit ${STATE_OK}
else
exit ${STATE_CRITICAL}
fi
exec 3<&-








Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts