.sh especificando extensão?

12

Por que alguns sistemas executam um .sharquivo apenas especificando o nome do arquivo sem extensão e outros requerem nome mais extensão? No meu caso, estou tentando escrever uma série de comandos seguindo estas instruções .

Estou especificando a extensão agora, mas ser capaz de executar os comandos sem .shseria preferível.

Philip Kirkbride
fonte
4
O uso .shcomo uma extensão é considerado, em muitas circunstâncias, uma prática inadequada: é contrário a como outros comandos são nomeados (você não executa ls.elf), geralmente é enganoso (se você foo.shcomeçar com #!/bin/bash, então a execução sh foo.shexecutará com um intérprete diferente do que foi criado para ) e, se você reescrever foo.shpara ser um programa Python, usar essa extensão significa escolher entre manter o nome agora enganoso e reescrever todos os programas que o chamam.
Charles Duffy
2
... onde é uma prática recomendada as bibliotecas de shell, não os comandos com +xset - onde foo.shé uma biblioteca que pode ser originada em qualquer shell POSIX, foo.bashpode ser originada no bash, foo.kshno ksh, etc.
Charles Duffy

Respostas:

39

Você está confuso. A .shextensão é apenas uma dica para os seres humanos e não tem absolutamente nenhum efeito sobre como o sistema lida com o arquivo. O Unix / Linux não cometeu nenhum Secrets.pdf.exeerro do Windows .

Aqui está o que acontece quando você digita foo:

  1. Redirecionamento para STDIN, STDOUTe STDERRsão criados.

  2. O shell verifica sua tabela de hash interna para ver se já conhece uma $PATHentrada foo. Se não houver, o shell pesquisará os diretórios $PATH, procurando um arquivo chamado fooque tenha o bit Execute definido nas permissões de arquivo. Primeiras foovitórias.

  3. Se os dois primeiros bytes do arquivo fooforem #!, a próxima sequência será o nome de um intérprete a ser executado. Assim, #!/bin/bashintroduz um script Bash, #!/usr/bin/perlintroduz um script Perl, etc.

  4. Se o arquivo começar \177ELF, é um executável binário e o ld.soinicia.

Leia man execvee man ld.sopara uma explicação mais detalhada.

waltinator
fonte
15
Sim, no Linux você pode clicar duas vezes Secrets.pdf sem nenhuma pista do nome que ele é realmente um executável;)
OrangeDog
1
@OrangeDog Eu sei que você está brincando, mas eu sinto que preciso apontar que o bit executável ( chmod +x) resolve isso, certo?
precisa saber é
3
@WChargin Isso depende de como o seu sistema de arquivos é bem-comportado (por exemplo, um compartilhamento de rede montado ou uma partição NTFS pode definir xtudo de maneira otimista ) e de onde veio o arquivo (qualquer processo com controle do diretório pode ser enganado para definir as permissões) . Então, isso mitiga , mas eu não diria que resolve .
IMSOP
2
@WChargin, ainda, mas acho que o argumento dele de que geralmente os gerenciadores de arquivos não mostram o bit executável, ou seja, não há "dica para humanos" como uma extensão.
Paul Draper
1
Eu nunca erroneamente clicar Secrets.pdf.exeporque eu sempre desativar o estúpido hide file extensionrecurso
phuclv
12

O ponto principal é o seguinte: as extensões são irrelevantes em qualquer sistema de sistema semelhante ao Unix. Um nome de arquivo é apenas o nome e não afeta se um script ou executável compilado pode ou não ser executado . Um programador pode adicionar uma .shextensão para designar que um arquivo é um script de shell ou .pypara um script python, mas, diferentemente do Windows, qualquer unix não se importa com nomes, se preocupa com permissões.

O que importa é a permissão executável concedida a um arquivo. Com o qual você pode verificar

ls -l /path/to/file

Executando executáveis

Para executar o script, geralmente existem várias maneiras.

  • Se seu diretório atual for o mesmo que o script e o script tiver permissões executáveis, você poderá executá-lo dessa maneira ./my_script_name. O .diretório atual significa.
  • Se o diretório atual for diferente e o script tiver permissões executáveis, você poderá executá-lo especificando o caminho completo: /home/user/bin/my_script_name

(Os dois métodos acima dependem do conjunto de permissões executáveis; se o arquivo faz parte ou não da $PATHvariável é irrelevante. A presença da #!linha também é importante; sem ela, o script será executado pelo shell atual que você abriu. Se eu tiver um cshscript sem essa linha e tente executá-lo no bash com ./my_script.csh, ele falhará)

  • Se o seu script estiver localizado no diretório que faz parte da sua $PATHvariável, você poderá executá-lo apenas chamando o nome. Você pode chamar o chmodcomando na linha de comando apenas digitando seu nome porque está na /binpasta. /binsempre faz parte da $PATHvariável Nesse caso, as permissões executáveis ​​e o local do script importam
  • Especificando um intérprete como comando e script como argumento. Dessa forma, o script servirá como arquivo de entrada para o intérprete.
  • Fornecendo um arquivo. O . filename.shou source filename.shvai fazer o script ser tratado como se fosse a entrada do teclado, ou seja, como se fosse digitado na linha de comando diretamente. Nesse caso, permissões executáveis ​​e localização não importam

Exemplos

Exemplo # 1, executando com intérprete, para permissões de exec

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Exemplo # 2, executando com ./conjunto de permissões executáveis, conjunto de linhas shebang.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Exemplo # 3, executando sem o conjunto de linhas shebang (falha, porque o bash não pode ler scripts python; nenhuma linha shebang assume o shell atual como intérprete)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Exemplo # 4, executando o script que possui permissões executáveis ​​define a pasta de formulário que faz parte da $PATHvariável

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

O Exemplo 5, removendo a extensão, ainda é executado porque as extensões não importam, mas tem permissões e faz parte de $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c
Sergiy Kolodyazhnyy
fonte
Executei o comando e recebo esse '-rwxr-x ---'. O que eu quero que o valor leia e como posso alterá-lo?
precisa saber é o seguinte
Ou você está dizendo que eu deveria simplesmente renomear 'filename.sh' para 'filename'?
precisa
1
@PhilipKirkbride O nome é irrelevante. Como você executa seu comando? Cadê ? O diretório faz parte do seu PATH?
Sergiy Kolodyazhnyy
@PhilipKirkbride Deixe-me expandir minha resposta em um minuto para torná-la mais clara.
precisa saber é o seguinte
1
Dê uma olhada man chmodpara ver como definir permissões
Nick Mertin
6

Boas explicações aqui já. Eu só queria acrescentar que, idealmente, você não deve usar extensões de arquivo para executáveis.

Geralmente, você precisa realizar algo relativamente fácil e começa com um pequeno script de shell. Com o tempo, você começa a adicionar cada vez mais funcionalidades ao seu script, até que chegue algum tempo que se torne impossível de manter ou você precise de alguma funcionalidade que não possa realizar facilmente com um shell script e pense em reescrever esse shell script em outro idioma (python , perl, ...?).

Reescrever do zero geralmente é considerado um erro, mas para scripts pode fazer sentido, porque geralmente eles não são tão grandes ou têm muitas funcionalidades. Mas vamos assumir que é possível reescrever do zero em alguma outra linguagem, mantendo a funcionalidade e os parâmetros / sinalizadores do script inicial do shell.

Os usuários desse script não precisam estar cientes dessa alteração de idioma, eles continuarão executando o mesmo comando e ele continuará funcionando.

Se seu script foi nomeado do-something.sh, ele pode continuar sendo do-something.sh, mas agora está escrito em python (por exemplo) e, portanto, sua dica inicial agora é totalmente enganosa.

Carlos Campderrós
fonte
4

Para executar arquivos sem uma extensão, você normalmente não precisa fazer muito, apenas certifique-se de ter (no caso de scripts bash) a linha shebang adequada na primeira linha:

#!/bin/bash

você também precisa tornar o arquivo executável para o sistema

chmod 755 yourfilename

É o mesmo que usar chmod +x yourfilenameos números que são fáceis de explicar.

É um número triplo de octais adicionados, o primeiro número representa o usuário, o segundo para o grupo e o terceiro para outros, mais sobre o que você pode encontrar aqui .

E se você estiver no mesmo diretório que o seu script, não se esqueça de usar ./assim:

./yourfilename
Videonauth
fonte
Tentei isso. Infelizmente, não há diferença dos resultados originais.
precisa saber é o seguinte
@PhilipKirkbride dê uma olhada na minha resposta revisada, isso provavelmente dará mais luz.
Videonauth
0

O sufixo .sh pode realmente atrapalhar, porque, para executá-lo, você deve digitar myscript.sh em vez de apenas myscript, o que não funcionará. É melhor chamá-lo de "myscript" sem o sufixo .sh, e um rápido uso do comando "file" dirá se é um executável binário (formato ELF no linux) ou um script de shell ou qualquer outro tipo de script.

O QDOS (sistema operacional rápido e sujo, que mais tarde foi renomeado para "DOS" pela IBM depois que a mirosoft o piratou e vendeu ilegalmente para eles) e outros ripoffs baratos do CP / M, incluindo janelas, misturam tudo isso porque nesses sistemas não há algo como executar permissões em arquivos. Isso resultou em incontáveis ​​conflitos de segurança nos últimos 30 a 40 anos. Na verdade, há apenas alguns minutos, recebi vários e-mails indesejados com um arquivo zip com armadilha renomeada para MYPICTURE.JPG.zip :)

delt
fonte