bash - bash:用于识别导致错误的特定别名的脚本
问题描述
[带有 GNU bash 5.0.3 的 Arch Linux v5.0.7]
一些.bashrc
别名似乎与andbash
提供的 shell 脚本冲突。我跟踪了运行脚本的问题,使用并启用了所有别名,最后看到脚本优雅地退出,退出代码为 0,只有当别名被禁用时。所以这与别名有关......但是哪一个?pyenv
pyenv-virtualenvwrapper
set -x
unalias -a
为了尝试自动化,我编写了下面的 shell 脚本:
- 它一次取消一个别名,从完整的别名列表中迭代读取,
- 它针对该留一别名配置测试冲突的 shell 脚本
test.sh
,并在检测到错误时打印一些内容, - 它撤消了以前的取消锯齿,
- 它继续取消别名下一个别名。
但是这两个内置函数在下面的脚本alias
中unalias
表现不佳cac.sh
:
#! /usr/bin/bash
[ -e aliases.txt ] && rm -f aliases.txt
alias | sed 's/alias //' | cut -d "=" -f1 > aliases.txt
printf "File aliases.txt created with %d lines.\n" \
"$(wc -l < <(\cat aliases.txt))"
IFS=" "
n=0
while read -r line || [ -n "$line" ]; do
n=$((n+1))
aliasedAs=$( alias "$line" | sed 's/alias //' )
printf "Line %2d: %s\n" "$n" "$aliasedAs"
unalias "$line"
[ -z $(eval "$*" 1> /dev/null) ] \ # check output to stderr only
&& printf "********** Look up: %s\n" "$line"
eval "${aliasedAs}"
done < <(tail aliases.txt) # use tail + proc substitution for testing only
像这样使用脚本:$ cac.sh test.sh [optional arguments to test.sh]
任何test.sh
都可以。它只需要返回一些非空字符串到标准错误。
第一个异常是该文件aliases.txt
是空的,就好像alias
无法从脚本中访问内置命令一样。如果我使用已填充的文件从其第 3 行启动脚本aliases.txt
,则脚本在 while 块内的第二行失败,再次好像alias
无法从脚本中调用一样。 任何建议表示赞赏。
注意:下面的一个衬里在控制台中工作:
$ n=0;while read -r line || [ -n "$line" ]; do n=$((n+1)); printf "alias %d : %s\n" "$n" "$(alias "$line" | sed 's/alias //')"; done < aliases.txt
解决方案
我通常建议不要将其实现为外部脚本——它作为一个可以直接在交互式 shell 中评估的函数更有意义(毕竟,所有可能涉及的别名都在其中定义)。
print_result() {
local prior_retval=$? label=$1
if (( prior_retval == 0 )); then
printf '%-30s - %s\n' "$label" WORKS >&2
else
printf '%-30s - %s\n' "$label" BROKEN >&2
fi
}
test_without_each_alias() {
[ "$#" = 1 ] || { echo "Usage: test_without_each_alias 'code here'" >&2; return 1; }
local alias
(eval "$1"); print_result "Unchanged aliases"
for alias in "${!BASH_ALIASES[@]}"; do
(unalias "$alias" && eval "$1"); print_result "Without $alias"
done
}
考虑以下:
rm_in_home_only() { [[ $1 = /home/* ]] || return 1; rm -- "$@"; }
alias rm=rm_in_home_only # alias actually causing our bug
alias red_herring=true # another alias that's harmless
test_without_each_alias 'touch /tmp/foobar; rm /tmp/foobar; [[ ! -e /tmp/foobar ]]'
...发出类似的东西:
Unchanged aliases - BROKEN
Without rm - WORKS
Without red_herring - BROKEN
请注意,如果您传递的代码执行一个函数,您需要确保该函数是在'd 代码中定义的;eval
由于别名是解析器的行为,它们发生在函数定义时,而不是函数运行时。
推荐阅读
- android - 与 EXPO 分离后的 Android Studio 错误
- ios - WebRTC:Safari 阻止视频画中画?
- ruby-on-rails - Rails 5 / Devise - 以管理员身份删除用户
- python - 如何获得稀疏矩阵的视图?
- android - Android 5.1.1 - 构建运行方式二进制
- python - Newton-Raphson 不工作 - 未来价值年金到期公式
- python - 如何将字符串添加到查询 django
- sql - SAS 中的高效滚动总和(窗口聚合)
- javascript - 按钮不适用于网络 Cookie Clicker 游戏
- gdb - 可以在 GDB 的回溯中显示共享库中的绝对地址吗?