Scrivere script shell che eseguiranno su qualsiasi shell (utilizzando più linee di shebang?)

Ho appena iniziato a approfondire lo script di shell e ho sempre gettato il mio script in un file, contrassegnato con chmod +x e poi fatto /path/to/script.sh e lasciato che qualsiasi interpretatore sia il default, ha il suo modo con esso, che ho assunto era zsh perché questo è quello che ho usato per la mia shell. A quanto pare sembra che sia solo /bin/sh per impostazione predefinita, anche se eseguo lo script da un prompt zsh perché ho iniziato a mettere in script i file specifico zsh e non riesco se non zsh /path/to/script.sh .

Per arrivare al punto, ecco le mie domande:

  1. Quale shell esegue gli script quando non esiste una linea di shebang ( #!/path/to/shell ) all'inizio? Suppongo /bin/sh ma non posso confermare.
  2. Quali sono considerate "best practice" in termini di scrittura di script shell che eseguiranno su qualsiasi piattaforma? (ok, questo è un tipo di open-ended)
  3. È ansible scrivere uno script che tenta di utilizzare zsh e torna a bash se zsh non è disponibile? Ho provato a mettere due linee di shebang, come qui sotto, ma sono solo gli errori con un bad interpnetworkingr: /bin/zsh: no such file or directory se provo su una macchina senza zsh.

    #!/bin/zsh

    #!/bin/bash

Quale shell esegue gli script quando non esiste una linea di shebang (#! / Path / to / shell) all'inizio? Suppongo / bin / sh ma non posso confermare.

Il kernel rifiuta di eseguire tali script e restituisce ENOEXEC, quindi il comportmento esatto dipende dal programma in cui eseguire un tale script.

  • bash 4.2.39 – utilizza se stesso
  • busybox-cenere 1.20.2 – utilizza se stessa
  • dash 0.5.7 – corre / bin / sh
  • pesce 1.23.1 – si lamenta di ENOEXEC, quindi incolpa il file sbagliato
  • AT & T ksh 93u + 2012.08.01 – utilizza se stesso
  • mksh R40f – funziona / bin / sh
  • pdksh 5.2.14 – funziona / bin / sh
  • sh-heirloom 050706 – si utilizza
  • tcsh 6.18.01 – funziona / bin / sh
  • zsh 5.0.0 – esegue / bin / sh
  • cmd.exe 5.1.2600 – ti guarda divertente.

In glibc , le funzioni execv() o execve() restituiscono appena ENOEXEC. Ma execvp() nasconde questo codice di errore e invoca automaticamente / bin / sh. (Questo è documentato in exec (3p) .)

Quali sono considerate "best practice" in termini di scrittura di script shell che eseguiranno su qualsiasi piattaforma? (ok, questo è un tipo di open-ended)

O attaccare a sh e solo le funzionalità definite POSIX, o semplicemente andare a bash (che è ampiamente disponibile) e menzionarlo nei tuoi requisiti se distribuirlo.

(Adesso che penso, Perl – o forse Python – sarebbe ancora più porttile, per non parlare di una migliore syntax.)

Aggiunga sempre la linea di splotzzo. Se si utilizza bash o zsh, utilizzare #!/usr/bin/env bash invece di codificare il path della shell. (Tuttavia, la shell POSIX è garantita in /bin/sh , quindi skip env in quel caso.)

(Purtroppo, anche /bin/sh non è sempre lo stesso. Il programma GNU autoconf deve affrontare molteplici richiami .)

È ansible scrivere uno script che tenta di utilizzare zsh e torna a bash se zsh non è disponibile? Ho provato a mettere due linee di shebang, come qui sotto, ma sono solo gli errori con un cattivo interpnetworking: / bin / zsh: nessun file o directory di questo tipo se provo su una macchina senza zsh.

Ci può essere solo una linea di splotzzo; tutto dopo il carattere newline non è nemless letto dal kernel e trattato come un commento da shell.

È ansible scrivere uno script che funziona come #!/bin/sh , controlla quale shell è disponibile e esegue exec zsh "$0" "[email protected]" o exec bash "$0" "[email protected]" seconda del risultato. Tuttavia, la syntax utilizzata da bash e zsh è così diversa in vari luoghi che non consiglierei di farlo per la tua sanità.

1) La shell corrente in cui si sta eseguendo. (Qualsiasi shell che possa essere)

2) Stick con lo stesso tipo di shell (bash / dash / ash / csh / qualunque sia il tuo sapore) e assicurati che le "piattaforms supportte" installino la shell che si desidera utilizzare per impostazione predefinita. Inoltre, prova a utilizzare comandi comunemente disponibili sui sisthemes. Evitare le opzioni specifiche per la macchina.

3) Non esiste una logica "if-then-else" alla interpnetworkingr directive . È necessario specificare una shell che dovrebbe esistere su tutti i sisthemes che si desidera sostenere … cioè #!/bin/bash o specificare un generico #!/bin/sh finché il tuo script è abbastanza generico in tutte le shell.