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 / 489628
Accepted
Harold Fischer
Harold Fischer
Asked: 2018-12-18 23:37:26 +0800 CST2018-12-18 23:37:26 +0800 CST 2018-12-18 23:37:26 +0800 CST

Por que o comportamento da sintaxe `#!` não é especificado pelo POSIX?

  • 772

Na página Shell Command Language da especificação POSIX:

Se a primeira linha de um arquivo de comandos shell começar com os caracteres "#!", os resultados não serão especificados.

Por que o comportamento de #!não especificado pelo POSIX? Acho desconcertante que algo tão portátil e amplamente usado tenha um comportamento não especificado.

shell posix
  • 3 3 respostas
  • 2552 Views

3 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2018-12-18T23:57:05+08:002018-12-18T23:57:05+08:00

    Acho que principalmente porque:

    • o comportamento varia muito entre a implementação. Veja https://www.in-ulm.de/~mascheck/various/shebang/ para todos os detalhes.

      No entanto, agora poderia especificar um subconjunto mínimo da maioria das implementações do tipo Unix: como #! *[^ ]+( +[^ ]+)?\n(com apenas caracteres do caractere de nome de arquivo portátil definido nessas uma ou duas palavras) onde a primeira palavra é um caminho absoluto para um executável nativo, a coisa não é muito longo e comportamento não especificado se o executável é setuid/setgid, e implementação definida se o caminho do interpretador ou o caminho do script é passado como argv[0]para o interpretador.

    • O POSIX não especifica o caminho dos executáveis ​​de qualquer maneira. Vários sistemas têm utilitários pré-POSIX em /bin/ /usr/bine têm utilitários POSIX em outro lugar (como no Solaris 10 onde /bin/shestá um Bourne shell e o POSIX está em /usr/xpg4/bin; Solaris 11 o substituiu por ksh93 que é mais compatível com POSIX, mas a maioria dos outros ferramentas /binainda são antigas não-POSIX). Alguns sistemas não são POSIX, mas possuem um modo/emulação POSIX. Tudo o que o POSIX exige é que haja um ambiente documentado no qual um sistema se comporte POSIXly.

      Veja Windows+Cygwin por exemplo. Na verdade, com o Windows+Cygwin, o she-bang é respeitado quando um script é invocado por um aplicativo cygwin, mas não por um aplicativo nativo do Windows.

      Portanto, mesmo que o POSIX tenha especificado o mecanismo shebang, ele não poderá ser usado para escrever scripts POSIX / sh/ sed... marcador).awksedawk

    Agora, o fato de não ser especificado não significa que você não pode usá-lo (bem, ele diz que você não deve começar com a primeira linha #!se espera que seja apenas um comentário regular e não um she-bang), mas que POSIX não lhe dá nenhuma garantia se você fizer isso.

    Na minha experiência, usar shebangs lhe dá mais garantia de portabilidade do que usar a maneira POSIX de escrever scripts de shell: deixe de fora o she-bang, escreva o script na shsintaxe POSIX e espere que o que quer que invoque o script invoque um POSIX compatível shcom ele, que é tudo bem se você souber que o script será invocado no ambiente certo pela ferramenta certa, mas não de outra forma.

    Você pode ter que fazer coisas como:

    #! /bin/sh -
    if : ^ false; then : fine, POSIX system by default
    else
      # cover Solaris 10 or older. ": ^ false" returns false
      # in the Bourne shell as ^ is an alias for | there for
      # compatibility with the Thompson shell.
      PATH=`getconf PATH`:$PATH; export PATH
      exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
    fi
    # rest of script
    

    Se você quiser ser portátil para Windows + Cygwin, talvez seja necessário nomear seu arquivo com uma extensão .batou e usar algum truque semelhante para ou invocar o cygwin no mesmo arquivo..ps1cmd.exepowershell.exesh

    • 22
  2. JdeBP
    2018-12-19T05:26:05+08:002018-12-19T05:26:05+08:00

    [O] comportamento parece consistente entre todos os shells de reclamação POSIX. Não vejo a necessidade de espaço de manobra aqui.

    Você não está olhando profundamente o suficiente.

    Na década de 1980, esse mecanismo não era padronizado de fato. Embora Dennis Ritchie a tenha implementado, essa implementação não chegou ao público no lado da AT&T do universo. Foi efetivamente apenas publicamente disponível e conhecido no BSD; com scripts de shell executáveis ​​não disponíveis no AT&T Unix. Assim, não era razoável padronizá-lo. O estado de coisas é exemplificado por este doco contemporâneo, um dos muitos:

    Observe que o BSD permite que os arquivos que começam com #! interpretersejam executados diretamente, enquanto o SysV permite que apenas os arquivos a.out sejam executados diretamente. Isso significa que uma instância de uma das exec…()rotinas em um programa BSD pode ter que ser alterada no SysV para executar o interpretador (tipicamente /bin/sh) para esse programa.
    — Stephen Frede (1988). "Programação no System X Versão Y". Boletim Australiano do Grupo de Usuários de Sistemas Unix . Volume 9. Número 4. p. 111.

    Um ponto importante aqui é que você está olhando para shells, enquanto a existência de scripts de shell executáveis ​​é, na verdade, uma questão de exec…()funções. O que os shells fazem inclui os precursores do mecanismo de script executável, ainda encontrado em alguns shells até hoje (e também hoje obrigatório para o exec…p()subconjunto de funções), e é um pouco enganoso. O que o padrão precisa abordar a esse respeito é como exec…()um script interpretado funciona e, no momento em que o POSIX foi originalmente criado , ele simplesmente não funcionava em grande parte do espectro de sistemas operacionais de destino .

    Uma questão secundária é por que isso não foi padronizado desde então, especialmente porque o mecanismo de número mágico para intérpretes de script atingiu o público no lado da AT&T do universo e foi documentado exec…()na Definição de Interface do Sistema 5 , na virada da década de 1990 :

    Um arquivo interpretador começa com uma linha do formato

    #! nome do caminho [arg]
    onde pathname é o caminho do interpretador e arg é um argumento opcional. Quando você execcria um arquivo interpretador, o sistema execé o interpretador especificado.
    — exec. Definição da Interface do System V . Volume 1. 1991.

    Infelizmente, o comportamento permanece hoje quase tão divergente quanto na década de 1980 e não há um comportamento verdadeiramente comum para padronizar. Alguns Unices (famosos HP-UX e FreeBSD, por exemplo) não suportam scripts como intérpretes de scripts. Se a primeira linha é um, dois ou muitos elementos separados por espaços em branco varia entre MacOS (e versões do FreeBSD anteriores a 2005) e outros. O comprimento máximo do caminho suportado varia. ␀e caracteres fora do conjunto de caracteres de nome de arquivo portátil POSIX são complicados, assim como espaços em branco iniciais e finais. O que os argumentos 0, 1 e 2 acabam sendo também é complicado, com variação significativa entre os sistemas. Alguns atualmente em conformidade com POSIX, mas não-Os sistemas Unix ainda não suportam nenhum mecanismo desse tipo, e sua obrigatoriedade os converteria em não serem mais compatíveis com POSIX.

    Leitura adicional

    • Qual interpretador de shell executa um script sem shebang?
    • Por que posso passar argumentos para /usr/bin/env neste caso?
    • script. Manual de Informações Diversas do NetBSD . 2005-05-06.
    • https://unix.stackexchange.com/a/605761/5132
    • 11
  3. jamesdlin
    2018-12-19T23:10:35+08:002018-12-19T23:10:35+08:00

    Conforme observado por algumas das outras respostas, as implementações variam. Isso torna difícil padronizar e preservar a compatibilidade com os scripts existentes. Isso é verdade mesmo para sistemas POSIX modernos. Por exemplo, o Linux não tokeniza totalmente a linha shebang por espaços. O macOS não permite que o interpretador de scripts seja outro script.

    Veja também http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability

    • 1

relate perguntas

  • Como funciona este comando? mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 1234 > /tmp/f

  • 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

  • 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

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 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

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 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
    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
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +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
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +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