Stank是用于嗅探文件的命令行实用程序的库和集合,以识别bash,sh,zsh,ksh等壳脚本,等等,那些时髦的farmfresh gobs of garbaggio;与其他更可口的文件,例如RB,PY,PL。
信不信由你,众所周知,Shell脚本很难写得很好,因此,开发人员应该用更安全的语言编写Shell脚本,或者用linters的臂棒制作您的脚本。麻烦的是,在大型项目中,人们永远无法确定哪些文件是诚实的,以符合POSIX符合POSIX的外壳脚本,哪些是假装的。 CSH,TCSH,FISH,ION,RC和bash的其他大多数非衍生物往往不兼容。如果您到目前为止已经足够愉快了,那么让我们以一些果味的例子来获取cackalackin!
为方便起见,Stank系统包括Stank GO库以及几个命令行实用程序。 stank应用程序扫描目录和文件的POSIX衍生的Shell脚本,并打印其路径,该路径是一种方便的独立过滤器,用于覆盖大量的源代码集合。
$ cd examples
$ stank .
.profile
.shrc
.zlogin
... stank命令行实用程序搜索文件路径,以查找可能需要覆盖的外壳脚本。
Stank与外部衬里集成在一起,有助于为他们提供更集中的文件路径集,以在较大的项目目录中进行分析。
$ 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...机器生成的文件,包括git挂钩默认*.sample样本文件,会自动跳过。
有关其他选项,请参见stank -help 。
https://github.com/mcandre/stank/releases
$ go install github.com/mcandre/stank/...@latesthttps://pkg.go.dev/github.com/mcandre/stank
funk Linter报告了脚本中发出的奇怪气味,例如不当行结尾,某些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和funk都可以选择低级别的非Posix脚本,例如FreeBSD中使用的CSH/TCSH脚本。
请注意,如果还缺少扩展,放克无法可靠警告丢失Shebangs;通常,脚本作者使用一个或另一个将文件标记为shell脚本。缺少shebang和文件扩展名,这意味着文件可以包含许多语言的代码,因此很难确定代码的效率。即使应用了一组详尽的AST来测试数十个可用的shell语言中语法有效性的文件内容,但在较短的文件中很有可能仅仅是附带有效的脚本语法,尽管文件的目的不是作为posix shell脚本操作。简而言之,诸如CSH/TCSH之类的非Posix脚本很容易触发“ POSIX”语法匹配。无论如何,都知道Shebang是确保正确解释您的脚本的必要条件。
请注意,如果将脚本放置在非unix文件系统(例如NTFS)上,则Funk可能不会出现权限警告,在该系统中,完全缺少文件元数据中的可执行文件。存储Shell脚本时,请确保设置适当的文件权限,并以tarball中的捆绑文件或类似的方式将文件传输为限制权限。
请注意,Funk可能会在文件名中警告口译员对带有无关点的脚本不匹配。而不是.envrc.sample ,命名文件sample.envrc 。而不是wget-google.com ,而是命名文件wget-google-com 。附加.sh也是一个选项,因此update.es.cluster renuames tow update.es.cluster.sh 。
可选的-modulino标志要放心,可以将脚本职责的严格分开,分为不同的应用程序脚本与库脚本。应用程序脚本通常是通过调用路径来执行的,例如./hello或~/bin/hello ,或者在适当修改$PATH时简单地hello 。应用程序脚本功能所有者可执行的权限,也许还有组和其他根据系统配置需求。相比之下,库脚本旨在用DOT( . )导入或source到用户外壳或其他脚本中,并应使用文件扩展名,例如.lib.sh , .sh , .bash等。通过使用单独的命名约定,我们更快地通信与下游用户与Shell脚本进行交互。特别是,通过删除Shell脚本应用程序的文件扩展名,我们鼓励作者选择更有意义的脚本名称。而不是通用build.sh ,请选择build-docker 。而不是kafka.sh ,选择start-kafka , kafka-entrypoint等。
最后, stink打印了每个文件的posixyness的记录,包括沿途确定的任何有趣的字段。请注意,如果Posix或Nonposix的玫瑰色链的臭味是压倒性的短路分析,则某些场可能为零。这种短路的功能极大地加快了搜索大型项目的stank 。
请注意,由于JSON Integer格式化的限制,权限是作为小数传递的(我们不想使用自定义八倍字符串字段)。使用echo 'obase=8;<some integer> | bc以八进制显示这些值。
请注意,引用“ SH”的旧系统,软件包和外壳脚本可能指的是众多的postex shell。现代系统将“ sh”重命名为“ lksh”,“ tsh”,“ etsh”等,以避免混乱。通常,Stank Suite将假设扫描的大多数脚本是针对1971年后技术的,因此请使用您的人类直觉和上下文来注意任何遗产Thompson Unix v6“ SH”等。大多数现代的衬里既无法分析任何复杂性的此类脚本,也不会为它们所识别的遗留脚本而认识到它们,除非脚本的“ Shebangs”与现代复古解释器“ LKSH”,“ TSH”,“ ETSH”等进行,以用于现代Unix系统上的部署。一个人几乎可以使用FS统计数据进行修改/更改来尝试识别这些遗产异常值,但这实际上是一个不切实际的假设,除了最痴迷的考古学家,即使经过实验性的内容修改,也要确保他们的遗产脚本继续展示1970年的元数据。因此,出于现代性和平衡的目的,Stank系统将简单地平底锅 - > sh-> posix sh,ksh-> ksh88 / ksh93。
同样,旧的Bourne Shell aka“ sh” aka“ bsh”提出了语言识别困难。旧的Bourne Shell脚本最有可能向“ SH” Shebangs展示自己,这是可以的,就像Bourne SH和KSH88/PDKSH/KSH一样,是Posix SH标准的基础。一些现代系统可能会以“ SH”或“ BSH”二进制形式出现Bourne Shell。前者列出了一些识别的问题,尽管“ BSH”很棘手,因为当今的大部分用途与Bourne Shell无关,而与Java Beanshell有关。因此,Stank可能会默认将bsh脚本视为非固定脚本,并建议任何此类Bourne Shell脚本都具有bash或sh shebangs,也许是.sh或.sh或.bash Extensions,以便自我识别为现代的POSIX符合POSIX的脚本。
$ 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随附的examples/目录演示了许多边缘案例,例如空脚本,无shebang脚本,扩展和扩展的脚本以及许多编程语言中的各种Hello World应用程序。某些文件(例如examples/goodbye可能包含100%有效的POSIX Shell脚本内容,但没有使用Shebangs或相关文件扩展名来自我识别。在一个大型项目中,可能会错误地将这些文件视为whoknowswhat格式,也可以简单地将其视为纯文本。也许统计方法可以帮助识别POSIX语法,但是即使是空的文件也是技术上的POSIX,从可靠的分类角度来看,这是无助的。无论如何, examples/希望涵盖更常见的边缘案例。
想到stank的一种方法是用于外壳脚本的赏金猎人。
鉴于外壳往往比更高级别的编程语言更脆弱,那么将Shell代码重写为专用应用程序是一个好主意。对于应用语言而言,生锈是特别的选择。
生锈的编程语言在班级表现,可靠性和安全性方面具有最佳状态。在大多数情况下,GO编程语言具有可比性的性能,可靠性和安全性。与片状壳脚本相比,Rust and Go支持交叉兼容和静态可执行文件,因此它更容易开发,测试,包装和分发Rust/Go应用程序。大多数壳牌编码者忽略了考虑使用Shell语法和用于单个命令的标志的微妙供应商锁定问题。 Rust的学习曲线比某些编码人员愿意花时间陡峭。通常,Go可以作为妥协。作为编译语言,生锈和GO都受到了许多运行时陷阱的保护,这些陷阱和其他解释的语言邀请了。
无论如何,只要不是外壳,特定的编程语言就不太重要,关注点。众所周知,诸如JavaScript和Perl之类的危险编程语言仍然比外壳更安全。壳(任何口味)是垃圾火等待火花。
幸运的是, stank发射的外壳脚本列表可以帮助工程师识别程序候选人以更成熟的编程语言重写。
BSD-2-cause
(没有任何)
有关发展本身的更多详细信息,请参见Development.md。
请注意,许多软件组件有一个不好的习惯,即鼓励嵌入式内联shell脚本片段到非shell脚本文件中。例如,CI/CD作业配置,Dockerfile运行步骤,Kubernetes资源和制造。大多数Linter工具(用于Shell脚本和其他语言)对覆盖Inline inline shell脚本片段的支持非常有限或不存在。
因此,将Shell脚本片段移至专用的Shell脚本文件。然后让软件组件执行Shell脚本。然后,您将能够使用更多工具来提起外壳代码,从而提高系统的质量水平。
一些相当晦涩的文件,例如带有多行的常见LISP源代码,多列表shebang和没有文件扩展名,可能会错误地触发stank库,以及臭味和stank应用程序,这些应用程序在hacky shebang的第一行上短路。这些文件可能被错误地识别为“ POSIX”代码,这实际上是预期的行为!这是因为Polyglot Shebang是在常见的LISP语言中限制的攻击,通常不接受Posix Shebang评论,以便让常见的LISP脚本在bash中被点击。对于这种情况,最好向此类文件提供适当的文件扩展名。
$ 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
}也许将.lisp扩展程序附加到此类文件。或将MODULINO分离为清除库与命令行模块。或将外壳相互作用提取到专用脚本中。或说服语言维护者将Shebang视为评论。写你的国会议员。但是,您可以解决这个问题,知道当前的情况远远超出了常态,并且可能以适当的奥术和戏剧性的方式破裂。带有飞船,燃烧的海洋和各种疾病的预兆。
这些不良的BOI有助于掩盖您的外壳脚本。尽管它们旨在处理单个文件,因此请确保施加较大的项目并将结果送到xargs [-0] [-n ... shellcheck 。
ACK提供 - 与stank相似的--shell [-f]标志,其中ACK在这些结果中包括CSH,TCSH和FISH等非斑点壳;但是截至撰写本文时,未能包括灰烬,破折号,Posh,Pdksh,KSH93和MKSH等POSIX壳。 ACK还取决于Perl,这使Docker微服务和其他受约束平台变得更加重量级。
Kirill确定了JSON文件。
语言学家,Github的非凡努力是为了确定其数百万个存储库中的每种语言。
Linters,一个常见编程语言衬里和SAST工具的Wiki。
潜望镜警告未指示的NPM软件包。
SAIL标识C/C ++源代码文件。
Slick提供sh -n语法对纯POSIX语法进行检查,而在大多数系统符号链接中,实际sh均可进行bash。
Unmake,Makefiles的衬里。