为什么当源文件表示脚本顶部的变量时 shellcheck 会失败?

Cur*_*Sam 14 bash scripting shellcheck

Ubuntu 16.04
Bash 4.3.48

shellcheck当源文件表示脚本顶部的$variables时,为什么会失败?

这是一个简单的脚本:

#!/bin/bash

. .sourcefile

echo "Today is ${day}."
Run Code Online (Sandbox Code Playgroud)

这是我的源文件:

day="Monday"
Run Code Online (Sandbox Code Playgroud)

以下是来自的回复shellcheck

me@myserver:~$ shellcheck start.sh

In start.sh line 5:
echo "Today is ${day}."
               ^-- SC2154: day is referenced but not assigned.
Run Code Online (Sandbox Code Playgroud)

有没有办法让shellcheck知道$变量是在源文件中?


这是我为在 Ubuntu 16.04 上完成这项工作所做的工作

@Dash-o 解释了以下程序:

首先,在源文件声明上方的行中添加source 指令,如下所示:
# shellcheck source=/path/to/sourcefile

#!/bin/bash

# shellcheck source=./.sourcefile
. .sourcefile

echo "Today is ${day}."
Run Code Online (Sandbox Code Playgroud)

接下来,在脚本之前shellcheck使用-x选项执行,如下所示:
shellcheck -x start.sh

me@myserver:~$ shellcheck -x start.sh
Run Code Online (Sandbox Code Playgroud)

使用-x选项时,shellcheck将遵循直接在源指令下方声明的源文件。当我执行命令时,我收到以下错误:

me@myserver:~$ shellcheck -x start.sh
unrecognized option `-x'

Usage: shellcheck [OPTIONS...] FILES...
  -e CODE1,CODE2..  --exclude=CODE1,CODE2..  exclude types of warnings
  -f FORMAT         --format=FORMAT          output format
  -s SHELLNAME      --shell=SHELLNAME        Specify dialect (bash,sh,ksh)
  -V                --version                Print version information
Run Code Online (Sandbox Code Playgroud)

@Bayou 提到我的操作系统需要更新版本的shellcheck. 我检查了我的 Ubuntu 16.04 安装。我的服务器有shellcheck0.3.7,这是 Ubuntu 16.04 必须提供的最新版本,所以我从shellcheck开发人员那里获取了最新的二进制文件并安装了它。

me@myserver:~$ mkdir .work && cd .work
me@myserver:~/.work$ wget -q https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz
me@myserver:~/.work$ ls

shellcheck-stable.linux.x86_64.tar.xz

me@myserver:~/.work$ tar xvf shellcheck-stable.linux.x86_64.tar.xz

shellcheck-stable/README.txt
shellcheck-stable/LICENSE.txt
shellcheck-stable/shellcheck

me@myserver:~/.work$ sudo chown root: shellcheck-stable/shellcheck
me@myserver:~/.work$ sudo mv /usr/bin/shellcheck .
me@myserver:~/.work$ sudo mv shellcheck-stable/shellcheck /usr/bin/
me@myserver:~/.work$ cd ../
me@myserver:~$ rm -rf .work/
me@myserver:~$ shellcheck -V

ShellCheck - shell script analysis tool
version: 0.7.1
license: GNU General Public License, version 3
website: https://www.shellcheck.net
Run Code Online (Sandbox Code Playgroud)

我运行了命令shellcheck -x start.sh,我收到了零错误。

me@myserver:~$ shellcheck -x start.sh
Run Code Online (Sandbox Code Playgroud)

然后我被迫shellcheck给我一些错误。我添加cat $myVariable到我的脚本的末尾。

me@myserver:~$ echo "cat \$myVariable" >> start.sh  
me@myserver:~$ cat start.sh
#!/bin/bash

# shellcheck source=./.sourcefile
. .sourcefile

echo "Today is ${day}."
cat $myVariable
Run Code Online (Sandbox Code Playgroud)

我测试了我的理论并shellcheck遵循了我的源文件并给出了我期望的错误。

me@myserver:~$ shellcheck -x start.sh

In start.sh line 7:
cat $myVariable
    ^---------^ SC2154: myVariable is referenced but not assigned.
    ^---------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean:
cat "$myVariable"

For more information:
  https://www.shellcheck.net/wiki/SC2154 -- myVariable is referenced but not ...
  https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
Run Code Online (Sandbox Code Playgroud)

然后我在shellcheck没有-x选项的情况下执行,令我惊讶的是我收到了以下错误:

me@myserver:~$ shellcheck start.sh

In start.sh line 4:
. .sourcefile
  ^---------^ SC1091: Not following: ./.sourcefile was not specified as input (see shellcheck -x).


In start.sh line 6:
echo "Today is ${day}."
               ^----^ SC2154: day is referenced but not assigned.


In start.sh line 7:
cat $myVariable
    ^---------^ SC2154: myVariable is referenced but not assigned.
    ^---------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean:
cat "$myVariable"

For more information:
  https://www.shellcheck.net/wiki/SC2154 -- day is referenced but not assigned.
  https://www.shellcheck.net/wiki/SC1091 -- Not following: ./.sourcefile was ...
  https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
Run Code Online (Sandbox Code Playgroud)

所以shellcheck更新到最新版本并且没有-x选项,也会给你一个关于你在命令行上错过-x选项的错误。所以我决定在我的 start.sh 中注释掉sourcefile 指令

me@myserver:~$ sed -i '3s/./#\ &/' start.sh
me@myserver:~$ cat start.sh
#!/bin/bash

# # shellcheck source=./.sourcefile
. .sourcefile

echo "Today is ${day}."
cat $myVariable
Run Code Online (Sandbox Code Playgroud)

现在看看怎么shellcheck

me@myserver:~$ shellcheck -x start.sh

In start.sh line 7:
cat $myVariable
    ^---------^ SC2154: myVariable is referenced but not assigned.
    ^---------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean:
cat "$myVariable"

For more information:
  https://www.shellcheck.net/wiki/SC2154 -- myVariable is referenced but not ...
  https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
Run Code Online (Sandbox Code Playgroud)

哇哦?所以看起来我的简单脚本真的不需要sourcefile 指令,或者 shellcheck 仍然看到sourcefile 指令被用数字符号注释掉,因为数字符号已经启动了源文件指令?因此,我完全删除了sourcefile 指令并注释掉了最后一行,该行引用了未在源文件中分配的myVariable变量。

me@myserver:~$ sed -i '3d' start.sh
me@myserver:~$ sed -i '$d' start.sh
me@myserver:~$ cat start.sh
#!/bin/bash

. .sourcefile

echo "Today is ${day}."  
Run Code Online (Sandbox Code Playgroud)

现在看看有什么shellcheck报道:

me@myserver:~$ shellcheck -x start.sh
Run Code Online (Sandbox Code Playgroud)

-x选项没有错误。现在为了检查在 Ubuntu 16.04 上最新版本的简单 shell 脚本的顶部是否不需要sourcefile 指令shellcheck,我在shellcheck没有-x选项的情况下执行。

me@myserver:~$ shellcheck start.sh

In start.sh line 3:
. .sourcefile
  ^---------^ SC1091: Not following: .sourcefile was not specified as input (see shellcheck -x).


In start.sh line 5:
echo "Today is ${day}."
               ^----^ SC2154: day is referenced but not assigned.

For more information:
  https://www.shellcheck.net/wiki/SC2154 -- day is referenced but not assigned.
  https://www.shellcheck.net/wiki/SC1091 -- Not following: .sourcefile was no...
Run Code Online (Sandbox Code Playgroud)

因此,简而言之,如果shellcheck没有遵循您的源文件,请shellcheck从开发人员的 github更新 - ( https://github.com/koalaman/shellcheck ) 并shellcheck使用-x选项通知有一个源文件要遵循,如下所示:

shellcheck -x script.sh  
Run Code Online (Sandbox Code Playgroud)

我希望这对某人有所帮助,因为这个网站每天都在帮助我!

das*_*h-o 16

Shellcheck 是一个静态分析工具。它不处理动态路径(基于变量或表达式)。作为替代方案,请考虑添加 source 指令。

例子:

# shellcheck source=./lib.sh
source "$(find_install_dir)/lib.sh"
Run Code Online (Sandbox Code Playgroud)

source= 指令告诉 shellcheck 动态生成的文件名的位置。从问题来看,这应该是.sourcefile.

记录在https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md


Jer*_*een 5

VSCode 修复

在VSCode中,可以在settings中设置一个参数:

{
  "shellcheck.customArgs": ["-x"]
}
Run Code Online (Sandbox Code Playgroud)

答案来自:https://unix.stackexchange.com/a/534690/231320