Stank est une bibliothèque et une collection d'utilitaires de ligne de commande pour renifler des fichiers afin d'identifier les scripts de coquille comme Bash, SH, Zsh, Ksh et ainsi de suite, ces gobes de farmfresh funky de Garbaggio; contre d'autres fichiers plus acceptables comme RB, PY, PL.
Croyez-le ou non, les scripts shell sont notoirement difficiles à bien écrire, donc il appartient à un développeur d'écrire des scripts de coquille dans des langues plus sûres, soit Wargame vos scripts avec une armada de liners. Le problème est que, dans les grands projets, on ne peut jamais être trop sûr des fichiers honnêtes pour les scripts de coquille conformes à Dog Posix et les prétendants. CSH, TCSH, FISH, ION, RC et la plupart des autres non-dérivés de Bash ont tendance à ne pas être compatibles POSIX. Si vous êtes assez geek pour avoir suivi jusqu'à présent, soyons Crackalackin avec quelques exemples fruités!
Le système STANK comprend la bibliothèque STANK GO ainsi que plusieurs utilitaires de ligne de commande pour plus de commodité. L'application stank analyse les répertoires et les fichiers pour les scripts de shell dérivés de POSIX et imprime leurs chemins, conçus comme un filtre autonome pratique pour lier de grandes collections de code source.
$ cd examples
$ stank .
.profile
.shrc
.zlogin
... L'utilitaire de commande de commande stank recherche des chemins de fichier pour les scripts shell qui peuvent justifier la liaison.
STANK s'intègre aux liners externes, aidant à leur nourrir un ensemble plus ciblé de chemins de fichiers pour analyser dans les répertoires de projet plus grands.
$ stank -print0 . | xargs -0 -n 1 shellcheck
In welcome.sh line 1:
#!bash
^----^ SC2239 (error): Ensure the shebang uses an absolute path to the interpreter.
For more information:
https://www.shellcheck.net/wiki/SC2239 -- Ensure the shebang uses an absolu... Les fichiers générés par la machine, y compris les fichiers Git Hook de défaut *.sample .
Voir stank -help pour des options supplémentaires.
https://github.com/mcandre/stank/releases
$ go install github.com/mcandre/stank/...@latesthttps://pkg.go.dev/github.com/mcandre/stank
Le funk Linter rapporte des odeurs étranges émanant des scripts, tels que des terminaisons de ligne inappropriées, la présence de marqueurs d'ordre d'octets dans certains scripts Unicode.
$ funk examples
Ambiguous launch style. Either feature a file extensions, or else feature executable bits: examples/.shrc
Tokenize like `unset IFS` at the top of executable scripts: examples/.shrc
Control program flow like `set -euf` at the top of executable scripts: examples/.shrc
Tokenize like `unset IFS` at the top of executable scripts: examples/badconfigs/zprofile
Control program flow like `set -euf` at the top of executable scripts: examples/badconfigs/zprofile
Missing shebang: examples/blank.bash
Traps may reset in subshells: examples/cleanup.sh
Missing shebang: examples/goodbye.sh
Missing shebang: examples/greetings.bash
Control program flow like `set -euf` at the top of executable scripts: examples/hello-commented
$ funk -modulino examples
Configuration features shebang: examples/badconfigs/.bash_profile
Configuration features executable permissions: examples/badconfigs/zprofile
Missing final end of line sequence: examples/blank.bash
Missing shebang: examples/blank.bash
Interpreter mismatch between shebang and extension: examples/derp.zsh
Missing shebang: examples/greetings.bash
Missing final end of line sequence: examples/hello-crlf.sh
CR/CRLF line ending detected: examples/hello-crlf.sh
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/hello-crlf.sh
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/howdy
Missing shebang: examples/howdy.zsh
Missing shebang: examples/just-eol.bash
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/lo
Missing final end of line sequence: examples/lo-cr.csh
CR/CRLF line ending detected: examples/lo-cr.csh
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/pipefail
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/shout.sh
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/wednesday
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/wednesday-bom
Leading BOM reduces portability: examples/wednesday-bom
Modulino ambiguity. Either have owner executable permissions with no extension, or else remove executable bits and use an extension like .lib.sh: examples/welcome
$ funk -help
-cr
Report presence/absence of final end of line sequence (default true)
-eol
Report presence/absence of final end of line sequence (default true)
-help
Show usage information
-modulino
Enforce strict separation of application scripts vs. library scripts
-version
Show version information stank et funk ont la possibilité de sélectionner également des scripts non Posix, tels que les scripts CSH / TCSH utilisés dans FreeBSD.
Notez que Funk ne peut pas avertir de manière fiable des shebang manquants si l'extension est également manquante; En règle générale, les auteurs de scripts utilisent l'un ou l'autre pour marquer les fichiers comme scripts shell. Le manque d'un shebang et d'une extension de fichier signifie qu'un fichier peut contenir du code pour de nombreuses langues, ce qui rend difficile la détermination de la nature positive du code. Même si un ensemble exhaustif d'AST est appliqué pour tester le contenu du fichier pour la validité syntaxique à travers les dizaines de langages de shell disponibles, il existe une forte possibilité dans les fichiers plus courts que le contenu ne soit que une syntaxe de script accidentellement valide, bien que l'intention du fichier ne soit pas de fonctionner comme un script de shell POSIX. Des scripts courts et non Posix tels que pour CSH / TCSH pourraient facilement déclencher une correspondance de syntaxe "POSIX". Dans tous les cas, sachez que le shebang est nécessaire pour s'assurer que vos scripts sont correctement interprétés.
Notez que Funk peut ne pas présenter les avertissements d'autorisations si les scripts sont hébergés sur des systèmes de fichiers non UNIX tels que NTFS, où des bits exécutables sont souvent manquants dans les métadonnées du fichier. Lors du stockage des scripts Shell, assurez-vous de définir les autorisations de fichiers appropriées et de transférer des fichiers en tant que bundle dans un tarball ou similaire à la sauvegarde contre les autorisations supprimées.
Notez que Funk peut avertir des décalages des interprètes pour les scripts avec des points étrangers dans le nom de fichier. Plutôt que .envrc.sample , nommez le fichier sample.envrc . Plutôt que wget-google.com , nommez le fichier wget-google-com . L'apprend .sh est également une option, donc update.es.cluster renoms à update.es.cluster.sh .
L'indicateur -modulino facultatif à Funk permet une séparation stricte des tâches de script, en scripts d'application distincts par rapport aux scripts de la bibliothèque. Les scripts d'application sont généralement exécutés en invoquant le chemin, tel que ./hello ou ~/bin/hello ou simplement hello lorsque $PATH est modifié de manière appropriée. Les scripts d'application présentent des autorisations exécutables du propriétaire, et peut-être le groupe et d'autres également en fonction des besoins de configuration du système. En revanche, les scripts de la bibliothèque sont destinés à être importés avec DOT ( . ) Ou source dans des shells utilisateur ou d'autres scripts, et devraient comporter une extension de fichier comme .lib.sh , .sh , .bash , etc. En utilisant des conventions de dénomination séparées, nous communiquons plus rapidement aux utilisateurs en aval comment interagir avec un script de shell. En particulier, en supprimant les extensions de fichiers pour les applications de script shell, nous encourageons les auteurs à choisir des noms de scripts plus significatifs. Au lieu de la build.sh générique.sh, choisissez build-docker . Au lieu de kafka.sh , choisissez start-kafka , kafka-entrypoint , etc.
Enfin, stink imprime un enregistrement de la posixie de chaque fichier, y compris les champs intéressants qu'il a identifiés en cours de route. Notez que certains champs peuvent être nuls nul si la puanteur de POSIX ou Rosy Waft de non-Posix est une analyse écrasante et court-circuisé. Cette fonctionnalité de court-circuisement accélère considérablement la façon dont stank recherche de grands projets.
Notez que les autorisations sont relayées sous forme de décimales, en raison de contraintes sur le formatage entier JSON (nous ne voulions pas utiliser un champ de chaîne octal personnalisé). Utiliser echo 'obase=8;<some integer> | bc pour afficher ces valeurs en octal.
Notez que les systèmes hérités, les packages et les scripts de coquille faisant référence à "SH" peuvent se référer à une pléthore de coquilles pré-Posix. Les systèmes modernes renomment "sh" à "lksh", "tsh", "eth", etc. pour éviter la confusion. En général, la suite pute supposera que la majorité des scripts scannés ciblent la technologie après 1971, alors utilisez votre intuition humaine et votre contexte pour noter tout héritage Thompson Unix V6 "Sh", etc. Scripts. La plupart des liners modernes ne pourront ni analyser ces scripts de toute complexité, et ils ne les reconnaîtront pas pour les scripts hérités qu'ils sont, à moins que les shebangs des scripts ne soient rendus avec les interprètes rétro modernes "LKSH", "TSH", "ETSH", etc. pour le déploiement sur les systèmes Unix modernes. On pourrait presque utiliser les statistiques FS pour la modification / le changement pour essayer d'identifier ces valeurs aberrantes héritées, mais il s'agit d'une hypothèse pratiquement irréaliste, à l'exception de l'archéologue le plus obsessionnel, garantissant avec diligence leurs scripts hérités continuent de présenter les métadonnées des années 1970 même après des modifications de contenu expérimental. Ainsi, le système de puanteur bottera simplement et supposera SH -> POSIX SH, KSH -> KSH88 / KSH93 pour le bien de la modernité et de l'équilibre.
De même, l'ancien Bourne Shell aka "Sh" aka "BSH" présente des difficultés d'identification linguistique. Les scripts de Shell Bourne Old Bourne sont plus susceptibles de se présenter des shebangs "sh", qui est correct en tant que Bourne SH et KSH88 / PDKSH / KSH a servi de base à la norme POSIX SH. Certains systèmes modernes peuvent présenter une coquille Bourne en tant que binaire "SH" ou "BSH". Le premier présente peu de problèmes pour l'identification de puant, bien que "BSH" soit délicat, car la majorité de ses utilisations aujourd'hui ne sont pas associées au Bourne Shell mais au Java Beanshell. Ainsi, le piste peut par défaut pour traiter les scripts bsh comme non positifs, et de tels scripts Bourne Shell sont invités à présenter des extensions bash ou sh .sh et peut-être des .bash .
$ stink examples/hello
{"Path":"examples/hello","Filename":"hello","Basename":"hello","Extension":"","Shebang":"#!/bin/sh","Interpreter":"sh","LineEnding":"n","FinalEOL":false,"ContainsCR":false
,"Permissions":509,"Directory":false,"OwnerExecutable":true,"BOM":false,"POSIXy":true,"AltShellScript":false}
$ stink -pp examples/hello
{
"Path": "examples/hello",
"Filename": "hello",
"Basename": "hello",
"Extension": "",
"Shebang": "#!/bin/sh",
"Interpreter": "sh",
"LineEnding": "n",
"FinalEOL": false,
"ContainsCR": false,
"Permissions": 509,
"Directory": false,
"OwnerExecutable": true,
"BOM": false,
"POSIXy": true,
"AltShellScript": false
}
$ stink -pp examples/hello.py
{
"Path": "examples/hello.py",
"Filename": "hello.py",
"Basename": "hello.py",
"Extension": ".py",
"Shebang": "#!/usr/bin/env python",
"Interpreter": "python",
"LineEnding": "n",
"FinalEOL": false,
"ContainsCR": false,
"Permissions": 420,
"Directory": false,
"OwnerExecutable": false,
"BOM": false,
"POSIXy": false,
"AltShellScript": false
}
$ stink -help
-cr
Report presence/absence of any CR/CRLF's
-eol
Report presence/absence of final end of line sequence
-help
Show usage information
-pp
Prettyprint smell records
-version
Show version information Les examples/ répertoire montrent de nombreux cas de bord, tels que des scripts vides, des scripts sans shebang, des scripts extensés et sans extension, et diverses applications Hello World dans de nombreux langages de programmation. Certains fichiers, tels que examples/goodbye peuvent contenir un contenu de script Shell POSIX 100% valide, mais ne vous identifient pas avec des shebangs ou des extensions de fichiers pertinentes. Dans un grand projet, ces fichiers peuvent être traités à tort comme un format whoknowswhat, ou simplement du texte brut. Peut-être que les méthodes statistiques pourraient aider à identifier les grammaires POSIX, mais même un fichier vide est techniquement POSIX, qui est inutile d'un point de vue de classification fiable. Dans tous les cas, examples/ espérons-le, couvrent les cas de bord les plus courants.
Une façon de penser au stank est un chasseur de primes pour les scripts de coquille.
Étant donné que Shell a tendance à être plus fragile que les langages de programmation de niveau supérieur, c'est une bonne idée de réécrire le code de shell en tant qu'applications dédiées. Allez et rouille sont des choix particulièrement bons pour les langues d'application.
Le langage de programmation Rust a le meilleur des performances, de la fiabilité et de la sécurité des classes. Le langage de programmation Go a des performances, une fiabilité et une sécurité comparables dans la plupart des contextes. Rust et GO prennent en charge la compilation croisée et les exécutables statiques, de sorte qu'il est beaucoup plus facile de développer, tester, emballer et distribuer des applications Rust / GO par rapport aux scripts de coquille feuilletée. La plupart des codeurs de shell négligent de considérer des problèmes de verrouillage subtils du fournisseur avec la syntaxe de la coquille et les drapeaux utilisés pour les commandes individuelles. Rust a une courbe d'apprentissage plus abrupte que certains codeurs sont prêts à consacrer du temps. Souvent, GO peut servir de compromis. En tant que langues compilées, la rouille et le go sont protégées de nombreux pièges d'exécution que les coquilles et les autres langues interprétées invitent.
Quoi qu'il en soit, le langage de programmation particulier est une préoccupation moins importante, tant qu'il ne s'agit pas de shell. Les langages de programmation notoirement dangereux comme JavaScript et Perl sont toujours plus sûrs que Shell. Shell (toute saveur) est un feu poubelle en attendant une étincelle.
Heureusement, la liste des scripts de shell qui émettent stank peuvent aider les ingénieurs à identifier les candidats du programme pour réécrire dans des langages de programmation plus matures.
Clause BSD-2
(Aucun)
Pour plus de détails sur le développement de STANK lui-même, voir Development.Md.
Notez que de nombreux composants logiciels ont la mauvaise habitude d'encourager les extraits de script en ligne intégrés dans des fichiers de script non coquille. Par exemple, les configurations de travail CI / CD, les étapes d'exécution DockerFile, les ressources Kubernetes et la création. La plupart des outils de linter (pour les scripts shell et autres langues) ont une prise en charge très limitée ou inexistante pour la liaison des extraits de script de shell en ligne.
En conséquence, déplacez les extraits de script shell vers un fichier de script de shell dédié. Puis demandez au composant logiciel d'exécuter le script shell. Ensuite, vous pourrez mener le code de shell avec plus d'outils et ainsi augmenter le niveau de qualité de votre système.
Certains fichiers plutôt obscurs, tels que le code source LISP commun avec des shebangs polyglots, des shebangs polyglots et aucune extension de fichier, peuvent déclencher faussement la bibliothèque puant, et les applications puantes et puant, qui court-circuit sur la première ligne du shebang hacky. Ces fichiers peuvent être faussement identifiés comme un code "POSIX", qui est en fait le comportement prévu! En effet, le polyglot shebang est un piratage pour contourner les limites du langage LISP commun, qui n'accepte généralement pas les commentaires de Shebang POSIX, afin d'obtenir des scripts LISP communs pour être slashables à DOT dans Bash. Pour cette situation, il est préférable de fournir une extension de fichier appropriée à ces fichiers.
$ head examples/i-should-have-an-extension
#!/usr/bin/env sh
#|
exec clisp -q -q $0 $0 ${1+"$@"}
|#
(defun hello-main (args)
(format t "Hello from main!~%"))
;;; With help from Francois-Rene Rideau
;;; http://tinyurl.com/cli-args
$ stink -pp examples/i-should-have-an-extension
{
"Path": "examples/i-should-have-an-extension",
"Filename": "i-should-have-an-extension",
"Basename": "i-should-have-an-extension",
"Extension": "",
"BOM": false,
"Shebang": "#!/usr/bin/env sh",
"Interpreter": "sh",
"LineEnding": "n",
"POSIXy": true
} Ajouter peut-être une extension .lisp à de tels fichiers. Ou séparez le modulino en modules Clear Library vs Command Line. Ou extraire l'interaction Shell dans un script dédié. Ou convaincre les mainteneurs linguistiques de traiter les shebang comme des commentaires. Écrivez votre membre du Congrès. Cependant, vous résolvez cela, sachez que la situation actuelle est bien en dehors de la norme, et susceptible de se briser de manière appropriée et dramatique. Avec Wyverns et les mers enflammées et les présages de toutes les manières malades.
Ces mauvais Bois aident à consolider vos scripts de coquille. Bien qu'ils soient conçus pour fonctionner sur des fichiers individuels, assurez-vous de puancer des projets plus grands et de tuer les résultats sur xargs [-0] [-n ... shellcheck .
ACK propose --shell [-f] drapeaux qui agissent de manière similaire à stank , avec la mise en garde qu'ACK comprend des coquilles non Posix comme CSH, TCSH et Fish dans ces résultats; Mais à ce jour, l'écriture n'inclut pas les obus POSIX comme Ash, Dash, Posh, PDKSH, KSH93 et MKSH. ACK dépend également de Perl, ce qui le rend plus lourd pour les microservices Docker et d'autres plates-formes contraises.
Kirill identifie les documents JSON.
LINGUIST, Effort extraordinaire de Github pour identifier la langue dans laquelle chacun de ses millions de référentiels est rédigé. Bien que ce projet Stanky Go n'utilise pas de linguiste dans une analyse automatisée, il convient de mentionner à des fins médico-légales, si vous rencontrez un fichier de code source étrange (ou mal identifié!).
Ligners, un wiki de liners de langage de programmation communs et d'outils de sast.
Periscope met en garde contre les packages NPM noncopés.
Sail identifie les fichiers de code source c / c ++.
Slick propose une vérification de la syntaxe sh -n contre la syntaxe POSIX pure, tandis que sh réel sur la plupart des systèmes Syminks à dénigrer.
Défendez-vous, un linter pour les makefiles.