有时,我碰巧正在执行某些命令,然后才意识到我向命令发送了错误的参数(例如重新启动 Heroku 应用程序)。我想修改 bash,如果它看到包含某个字符串的命令,它会提示我是否确定。例如(想象字符串是 tempus ):
$ heroku restart --app tempus
现在,我希望 bash 使用 Y/N 提示来提示我,如果我键入y
,那么我希望它执行命令。如果我键入 N,则不会执行该命令。我该如何处理这个问题?
有时,我碰巧正在执行某些命令,然后才意识到我向命令发送了错误的参数(例如重新启动 Heroku 应用程序)。我想修改 bash,如果它看到包含某个字符串的命令,它会提示我是否确定。例如(想象字符串是 tempus ):
$ heroku restart --app tempus
现在,我希望 bash 使用 Y/N 提示来提示我,如果我键入y
,那么我希望它执行命令。如果我键入 N,则不会执行该命令。我该如何处理这个问题?
我不知道有什么方法可以拦截所有 bash 命令,但是您可以使用以下技巧拦截预定的命令。
~/interception
)并将其设置为第一个条目$PATH
在该目录中创建以下脚本,其中包含您希望拦截的命令列表以及实际命令的完整路径
[bash]$ cat intercept.sh
#!/bin/bash
# map commands to full path
declare -A COMMANDS
COMMANDS[heroku]=/usr/bin/heroku
COMMANDS[grep]=/bin/grep
# ... more ...
CMD=$(basename $0) # command used to call this script
if [[ ! -z "${COMMANDS[$CMD]+x}" ]]; then # mapping found
# Do what you wish here. You can even modify/inspect the params.
echo "intercepted $CMD command... "
${COMMANDS[$CMD]} $@ # run actual command with all params
else
echo "Unknown command $CMD"
fi
在同一目录中,使用您希望拦截的命令的名称创建指向该脚本的符号链接
[bash]$ ln -s intercept.sh grep
[bash]$ ln -s intercept.sh heroku
现在,每次调用命令时,都会通过符号链接调用该脚本,然后它可以在调用实际命令之前执行您的出价。
您可以通过$COMMANDS
从配置文件中获取并创建辅助命令来进一步扩展此配置文件并创建/删除符号链接。然后,您将能够使用以下命令管理谁设置:
intercept_add `which heroku`
intercept_remove heroku
intercept_list
因为 bash 本身不支持命令行过滤,所以无法拦截命令。
这是一个肮脏的解决方案:
prefilter()
函数,如果它被声明。prefilter()
函数失败,则取消该命令。来源:cmd-wrap.sh
#!/bin/bash # The shebang is only useful for debug. Don't execute this script.
function create_wrapper() {
local exe="$1"
local name="${exe##*/}"
# Only create wrappers for non-builtin commands
[ `type -t "$name"` = 'file' ] || return
# echo "Create command wrapper for $exe"
eval "
function $name() {\
if [ \"\$(type -t prefilter)\" = 'function' ]; then \
prefilter \"$name\" \"\$@\" || return; \
fi; \
$exe \"\$@\";
}"
}
# It's also possible to add pre/post hookers by install
# [ `type -t \"$name-pre\"` = 'function' ] && \"$name-pre\" \"\$@\"
# into the dynamic generated function body.
function _create_wrappers() {
local paths="$PATH"
local path
local f n
while [ -n "$paths" ]; do
path="${paths%%:*}"
if [ "$path" = "$paths" ]; then
paths=
else
paths="${paths#*:}"
fi
# For each path element:
for f in "$path"/*; do
if [ -x "$f" ]; then
# Don't create wrapper for strange command names.
n="${f##*/}"
[ -n "${n//[a-zA-Z_-]/}" ] || create_wrapper "$f"
fi
done
done
unset _create_wrappers # Remove the installer.
unset create_wrapper # Remove the helper fn, which isn't used anymore.
}
_create_wrappers
要将它用于您的问题:
在 bash 中获取它:
. ./cmd-wrap.sh
创建您的版本prefilter()
以检查是否有任何参数包含该字符串:
function prefilter() {
local a y
for a in "$@"; do
if [ "$a" != "${a/tempus}" ]; then
echo -n "WARNING: The command contains tempus. Continue?"
read y
[ "$y" = 'Y' ] || [ "$y" = 'y' ]
return $?
fi
done
return 0
}
跑
heroku restart --app tempus
但不是
/usr/bin/heroku restart --app tempus
使用包装器功能。
最简单的方法是使用别名。这个简单的例子应该适合你:
这可以防止在参数中使用 tempus 执行 heroku 命令
function protect_heroku {
# use grep to determine if the bad string is in arguments
echo "$*" | grep tempus > /dev/null
# if string is not in arguments
if [ $? != 0 ]; then
# run the protected command using its full path, so as not to trigger alias
/path/to/heroku "$@"
else
# get user confirmation
echo -n Are you sure \(y/n\)?' '
read CONFIRM
if [ "$CONFIRM" = y ]; then
# run the protected command using its full path
/path/to/heroku "$@"
fi
fi
}
# This is the key:
# This alias command means that 'heroku' from now refers
# to the function protect_heroku, rather than /bin/heroku
alias heroku=protect_heroku
将此代码放入您的 bash 配置文件 ~/.profile,然后注销并重新登录。从现在开始,bash 将保护您免于意外使用 tempus 运行 heroku。
最简单的方法是替换heroku
为在执行真正的heroku 之前进行检查的脚本。另一种方法是为heroku
.