Inclua mais instruções sobre como executar o arquivo no hashbang ou em outro lugar

5

Eu tenho isso no topo de um script

#!/usr/bin/env mocha

como a maioria das pessoas sabe, isso informa ao SO qual executável usar para executar o script.

No entanto, minha pergunta é: como podemos incluir mais informações no executável mocha sobre como executar o script?

o mocha aceita argumentos opcionais, então eu gostaria de fazer algo assim:

#!/usr/bin/env mocha --reporter=tap --output=foo

mas não acho que isso seja permitido.

Como posso dar ao executável mocha mais informações sobre como executar o arquivo?

    
por Alexander Mills 25.03.2017 / 00:24

4 respostas

9

A linha shebang é interpretada pelo kernel e não é muito flexível. No Linux, ele é limitado a um único argumento: a sintaxe é #! , espaços em branco opcionais, caminho para o interpretador (sem espaço em branco), espaço em branco opcional e, opcionalmente, um único argumento (que pode conter espaços em branco, exceto no início). Além disso, o tamanho total da linha shebang é limitado a 128 bytes ( BINPRM_BUF_SIZE constante nas fontes do kernel, usada em load_script ).

Se você quiser passar mais de um argumento, precisará de uma solução alternativa. Se você estiver usando #!/usr/bin/env para expansão de caminho, então só há espaço para o nome do comando e nenhum outro argumento.

A solução mais óbvia é um script de wrapper. Em vez de ter /path/to/my-script contendo o código mocha, coloque o código mocha em outro arquivo /path/to/my-script.real e torne /path/to/my-script um pequeno script de shell. Aqui está um wrapper de amostra que assume que o código real está em um arquivo com o mesmo nome do script, além de .real no final.

#!/bin/sh
exec mocha --reporter=tap --output=foo "$0.real" "$@"

Com um invólucro de shell, você pode aproveitar a oportunidade para fazer coisas mais complexas, como definir variáveis de ambiente, procurar versões de intérprete disponíveis, etc.

Usando exec antes que o interpretador garanta que o script mocha seja executado no mesmo processo que o wrapper shell. Sem exec , dependendo do shell, ele pode ser executado como um subprocesso, o que importa, e. se você quiser enviar sinais para o script.

Às vezes, o script wrapper e o código real podem estar no mesmo arquivo, se você conseguir escrever um poliglota - um arquivo que é um código válido em dois idiomas diferentes. Escrever poliglotas nem sempre é fácil (ou até possível), mas tem a vantagem de não precisar gerenciar e implantar dois arquivos separados. Aqui está um JavaScript / shell poliglota em que a parte do shell executa o interpretador de JS no arquivo (supondo que o interpretador de JS ignore a linha shebang, não há muito o que fazer se não o fizer):

#!/bin/sh
///bin/true; exec mocha --reporter=tap --output=foo "$0" "$@"
… (the rest is the JS code) …
    
por 25.03.2017 / 01:27
3

Como resposta a resposta de Gilles , aqui está um invólucro independente. Esta é uma mistura de suas duas soluções. Tem as vantagens do script poliglota mencionado por Gilles (um script para manter e implantar) sem seus inconvenientes (citando Gilles: "Escrever poliglotas nem sempre é fácil ou até mesmo possível").

Consiste em adicionar apenas algumas linhas no topo do seu script:

#!/bin/bash
exec mocha --reporter=tap --output=foo <(sed -n '/^#MOCHA_START#/,$ p' "$0")
#MOCHA_START#
....
....
(mocha script)
....
....

O que segue a linha #MOCHA_START# é o seu script de moca real deixado intacto. O que as três primeiras linhas fazem é extrair seu roteiro mocha e chamar o mocha junto com os argumentos desejados.

No entanto, você pode ter que forçar seu editor de texto a interpretar o arquivo como um script Mocha e colorizá-lo adequadamente, pois ele provavelmente ficará confuso com a primeira linha do seu script, o que indica que é um script Bash:

    
por 25.03.2017 / 01:41
1

Uma das desvantagens de usar a linha #!/usr/bin/env shebang é que não podemos transmitir argumentos.

No entanto, você pode passar argumentos se usar o caminho para o seu intérprete:

#!/path/to/mocha --reporter=tap --output=foo

Veja também:

por 25.03.2017 / 00:42
0

A única maneira que eu atualmente sei como fazer isso é com variáveis env, então no meu hashbang eu tenho isso:

#!/usr/bin/env mocha

... E mocha, ou qualquer executável, terá que aceitar variáveis de ambiente , em vez de argumentos de linha de comando, para que funcione corretamente.

Isso, infelizmente, é muito limitante, porque muitos executáveis não usam variáveis env, então isso dificulta muito as bibliotecas, que precisam invocar outras bibliotecas, etc.

    
por 25.03.2017 / 01:22