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 / unix / Perguntas / 497526
Accepted
Sopalajo de Arrierez
Sopalajo de Arrierez
Asked: 2019-01-30 11:11:24 +0800 CST2019-01-30 11:11:24 +0800 CST 2019-01-30 11:11:24 +0800 CST

Script de shell do Linux: execute um programa apenas se ele existir, ignore-o se não existir

  • 772

Estou programando um script de shell do Linux que imprimirá banners de status durante sua execução somente se a ferramenta apropriada, digamos figlet, estiver instalada (isto é: alcançável no caminho do sistema ).

Exemplo:

#!/usr/bin/env bash
echo "foo"
figlet "Starting"
echo "moo"
figlet "Working"
echo "foo moo"
figlet "Finished"

Eu gostaria que meu script funcionasse sem erros mesmo quando não figletestá instalado .

O que poderia ser um método prático ?

shell scripting
  • 8 8 respostas
  • 11572 Views

8 respostas

  • Voted
  1. Best Answer
    Jeff Schaller
    2019-01-30T12:20:15+08:002019-01-30T12:20:15+08:00

    Minha interpretação usaria uma função wrapper com o mesmo nome da ferramenta; nessa função, execute a ferramenta real se ela existir:

    figlet() {
      if command -p figlet  >/dev/null 2>&1
        then 
          command figlet "$@"
        else
          :
        fi
    }
    

    Então você pode ter figlet arg1 arg2...inalterado em seu script.

    @Olorin surgiu com um método mais simples: defina uma função wrapper somente se precisarmos (se a ferramenta não existir):

    if ! command -v figlet > /dev/null; then figlet() { :; }; fi
    

    Se você quiser que os argumentos figletsejam impressos mesmo que o figlet não esteja instalado, ajuste a sugestão de Olorin da seguinte forma:

    if ! command -v figlet > /dev/null; then figlet() { printf '%s\n' "$*"; }; fi
    
    • 38
  2. roaima
    2019-01-30T11:16:54+08:002019-01-30T11:16:54+08:00

    Você pode testar para ver se figletexiste

    if type figlet >/dev/null 2>&1
    then
        echo Figlet is installed
    fi
    
    • 16
  3. kasperd
    2019-01-30T13:28:18+08:002019-01-30T13:28:18+08:00

    Uma maneira comum de fazer isso é com test -xaka [ -x. Aqui está um exemplo retirado de /etc/init.d/ntpum sistema Linux:

    if [ -x /usr/bin/lockfile-create ]; then
        lockfile-create $LOCKFILE
        lockfile-touch $LOCKFILE &
        LOCKTOUCHPID="$!"
    fi
    

    Essa variante depende de conhecer o caminho completo do executável. Em /bin/lesspipeencontrei um exemplo que contorna isso combinando -xe o whichcomando:

    if [ -x "`which bunzip`" ]; then bunzip -c "$1"
    else echo "No bunzip available"; fi ;;
    

    Dessa forma, isso funcionará sem saber com antecedência onde está PATHo bunzipexecutável.

    • 7
  4. Chris
    2019-01-31T03:04:05+08:002019-01-31T03:04:05+08:00

    No início do seu script, verifique se figletexiste e, se não existir, defina uma função shell que não faça nada:

    type figlet >/dev/null 2>&1 || figlet() { :; }
    

    typeverifica se figletexiste como shell embutido, função, alias ou palavra-chave, >/dev/null 2>&1descarta stdin e stdout para que você não obtenha nenhuma saída e, se não existir, figlet() { :; }define figletcomo uma função que não faz nada.

    Dessa forma, você não precisa editar todas as linhas do seu script que usam figlet, ou verificar se ele existe toda vez que figleté chamado.

    Você pode adicionar uma mensagem de diagnóstico, se desejar:

    type figlet >/dev/null 2>&1 || { echo 'figlet not installed.' ; figlet() { :; } ; }
    

    Como um bônus, já que você não mencionou qual shell está usando, acredito que seja compatível com POSIX, portanto, deve funcionar em praticamente qualquer shell.

    • 6
  5. rrauenza
    2019-01-30T13:52:03+08:002019-01-30T13:52:03+08:00

    Outra alternativa - um padrão que vi nos scripts de configuração automática do projeto:

    if [ -x /usr/bin/figlet ]
    then
        FIGLET=/usr/bin/figlet
    else
        FIGLET=:
    fi
    
    $FIGLET "Hello, world!"
    

    No seu caso específico você poderia até fazer,

    if [ -x /usr/bin/figlet ]
    then
       SAY=/usr/bin/figlet
    elif [ -x /usr/local/bin/figlet ]
    then
       SAY=/usr/local/bin/figlet
    elif [ -x /usr/bin/banner ]
    then
       SAY=/usr/bin/banner
    else
       SAY=/usr/bin/echo
    fi
    
    $SAY "Hello, world!"
    

    Se você não conhece o caminho específico, pode tentar vários elif(veja acima) para tentar locais conhecidos ou apenas usar o PATHpara sempre resolver o comando:

    if command -v figlet >/dev/null
    then
        SAY=figlet
    elif command -v banner >/dev/null
    then
        SAY=banner
    else
        SAY=echo
    fi
    

    Em geral, ao escrever scripts, prefiro chamar apenas comandos em locais específicos especificados por mim. Não gosto da incerteza/risco do que o usuário final pode ter colocado em seu PATH, talvez em seu próprio ~/bin.

    Se, por exemplo, eu estivesse escrevendo um script complicado para outros que possam remover arquivos com base na saída de um comando específico que estou chamando, não gostaria de pegar acidentalmente algo em seus ~/binque pode ou não ser o comando Eu esperava.

    • 5
  6. Vercingatorix
    2019-01-30T13:56:31+08:002019-01-30T13:56:31+08:00
    type -p figlet > /dev/null && figlet "foo"
    

    O comando bash typeencontra um comando, função, alias, palavra-chave ou built-in (consulte help type) e imprime a localização ou definição. Ele também retorna um código de retorno representando o resultado da pesquisa; verdadeiro (0) se encontrado. Então, o que estamos fazendo aqui é tentar encontrar figletno caminho ( -psignifica apenas procurar arquivos, não built-ins ou funções, e também suprime mensagens de erro), descartar a saída (é isso que > /dev/nullfaz) e se retornar true ( &&) , ele será executado figlet.

    Isso é mais simples se figletestiver em um local fixo:

    [ -x /usr/bin/figlet ] && /usr/bin/figlet "foo"
    

    Aqui estamos usando o testcomando (aka [) para ver se /usr/bin/figleté executável ( -x) e se sim ( &&) execute-o. Esta solução eu acho que é mais portátil do que usar typeo que é um bashism que eu acredito.

    Você pode criar uma função que faça isso para você:

    function x() {
        if type -p "$1" >/dev/null; then
            cmd="$1"
            shift
            "$cmd" "$@"
        fi
    }
    

    (As aspas são necessárias devido a possíveis espaços)

    Então você só faria:

    x figlet "foo"
    
    • 3
  7. jusdepatate
    2019-01-31T01:49:55+08:002019-01-31T01:49:55+08:00

    o/, eu diria algo como

    #!/usr/bin/env bash
    # if figlet is installed :
    if [ "$(which figlet 2>/dev/null)" ]; then
           # do what you wanted to do
           echo "foo"
           figlet "Starting"
           echo "moo"
           figlet "Working"
           echo "foo moo"
           figlet "Finished"
    # if not
    else
           # exit program with an error
           echo "please install figlet"
           exit 1
    fi
    
    • 1
  8. nigel222
    2019-02-01T02:50:39+08:002019-02-01T02:50:39+08:00

    Você pode fazer uma execução de teste, suprimindo qualquer saída e testar o código de sucesso/falha. Escolha argumentos para figlet para tornar este teste barato. -? ou --help ou --version são possibilidades óbvias.

    if figlet --help >/dev/null 2>&1 ; then
        # figlet is available
        echo "foo"
        figlet "starting"
        #etc
    else
        rc=$?
        echo "figlet is not installed or not working correctly (return code ${rc})"
    fi
    

    Adicionado em resposta ao comentário abaixo: se você realmente deseja testar se o figlet existe, não que seja utilizável, você faria

    figlet --help >/dev/null 2>&1 
    rc=$?
    if [ $rc -eq 127 ] ; then # 127 is "command not found" on linux bash 4.4.23(1)
        echo "command figlet not found"
    else
        figlet "whatever" # use figlet
    fi
    
    • 0

relate perguntas

  • FreeBSD's sh: funções de lista

  • Existe uma maneira de fazer ls mostrar arquivos ocultos apenas para determinados diretórios?

  • o que grep -v grep faz

  • Renomeie (acrescentar) arquivos CSV em massa com base em um valor dentro

  • Como salvar um caminho com ~ em uma variável?

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