我想从配置文件配置bash脚本。
我想提供一种种安全可靠的解决方案。
因此,对于我来说,选择源配置文件的最“常见”解决方案不是我的选择,因为下面的配置文件会做一些有趣的事情:
touch your_computer_is_hacked
foo=bar
配置文件的最佳做法是什么? 所以我可以将所有值都放在一个关联数组中吗?我不在乎实际的格式(bash脚本,yaml,ini,xml,javascript),但是应该完全指定它,因此如果我想添加空格/换行符或ő字符对于foo变量,应指定操作方法。
答案 0 :(得分:0)
我认为您最好的选择是编写source <(...)
,其中...
是从标准输入中读取并写出所需映射的命令。这样,...
可以是Perl脚本,Python脚本或其他任何东西,这比在纯Bash中执行此操作容易。
此答案的底部是一个满足您要求的简单示例。它创建了一个名为source-assoc-array
的函数,该函数使用从标准输入中读取的信息(通常会从文件中重定向)填充由调用方指定的关联数组(调用方需要预先声明)。传递标准输入的格式如下:
key=value
的形式。不允许使用空格,当然value
可以包含空格。\n
;反斜杠表示为\\
;所有其他字节均表示为自己。foo='bar\n\\\nbaz'
是关联数组的名称,则将行arr[foo]=$'\'bar\n\\\nbaz\''
转换为arr
。您可以通过支持各种功能(例如空行,注释,前导和尾随空格(包括尾随回车符,以支持Windows行尾),=
周围的空格,以及\n
和\\
之外的其他转义序列。
您可能还需要考虑一下威胁模型。例如,如果用户在文件中放入奇怪的字符(回车,从右到左的字符,控制字符等),是否使系统管理员很难准确地理解映射是什么问题? (由于以下原因,下面的函数会发出不包含有问题的行的错误消息-仅包含行号。)用户可以欺骗您的脚本以读取大量文件,导致Bash内存不足,或读取/dev/random
之类的设备文件?当然,任何这样的配置都会自动意味着用户的输入会影响脚本的以后行为。您需要确保没有任何可能的影响是您认为有害的。
无需做进一步的工作,这里是功能:
source-assoc-array() {
if [[ "$1" = -- ]] ; then
shift
fi
if [[ "$#" != 1 ]] ; then
echo 'Usage: source-assoc-array ARRAY_NAME < FILE' >&2
return 1
fi
if ! [[ "$(declare -p -- "$1" 2>&1)" == 'declare -A '* ]] ; then
printf '[%s] is not an associative array.\n' "$1" >&2
return 1
fi
source <(
perl -w -e '
my $array_name = $ARGV[0];
while (<STDIN>) {
unless (m/^([^=]*)=(.*)$/) {
die "[source-assoc-array] Error on line $.: No equals sign.\n";
}
my ($key, $val) = ($1, $2);
unless ($key =~ m/^[A-Za-z_][A-Za-z0-9_]*$/) {
die "[source-assoc-array] Error on line $.: Invalid key.\n";
}
if ($val =~ m/\0/) {
die "[source-assoc-array] Error on line $.: Null byte.\n";
}
unless ($val =~ m/^(?:[^\\]|\\[\\n])*$/) {
die "[source-assoc-array] Error on line $.: Unescaped backslash.\n";
}
$val =~ s/\x27/\\\x27/g; # escape single-quotes
print "$array_name\[$key]=\$\x27$val\x27\n";
}
' -- "$1" \
|| echo 'return 1'
)
}