经常,当我使用 切换 root 用户时,控制台中甚至 TTY 中su -
都会出现奇怪的bash
错误消息。即使在从头开始进行完整的系统升级后,这种情况仍然会发生,因此这可能是HOME 中的问题。rxvt
root
例如,这些:
sh: error importing function definition for `_file'
sh: _file: line 3: syntax error near unexpected token `('
sh: _file: line 3: ` --help | --version | --separator | -!(-*)[vF])'
当我注销时,出现几个错误,例如:
/bin/bash: _sudo: line 19: syntax error near unexpected token `('
/bin/bash: _sudo: line 19: ` --user | --other-user | -!(-*)[uU])'
/bin/bash: error importing function definition for `_sudo'
即使我sh
在控制台中这样做,我也会得到
/bin/bash: _file: line 3: syntax error near unexpected token `('
/bin/bash: _file: line 3: ` --help | --version | --separator | -!(-*)[vF])'
/bin/bash: error importing function definition for `_file'
然后我注销并再次登录,恢复正常行为。直到它开始表现得很奇怪……
我以为这是“~/.bashrc”或类似文件的问题,但这些文件与我的普通用户共享,而普通用户从来不会在控制台中显示错误。
显然有一个bash
脚本有错误,但我甚至不知道从哪里开始查找。这是什么_sudo
?命令什么grep _sudo $(find . -type f)
也find . -name _sudo
没显示...
编辑
这是我的文件的内容/usr/share/bash-completion/completions/sudo
:
# bash completion for sudo(8) -*- shell-script -*-
_sudo()
{
local cur prev words cword split
_init_completion -s || return
local i mode=normal
[[ $1 == *sudoedit ]] && mode=edit
[[ $mode == normal ]] &&
for ((i = 1; i <= cword; i++)); do
if [[ ${words[i]} != -* ]]; then
local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
local root_command=${words[i]}
_command_offset $i
return
fi
if [[ ${words[i]} == -@(!(-*)e*|-edit) ]]; then
mode=edit
break
fi
[[ ${words[i]} == \
-@(user|other-user|group|close-from|prompt|!(-*)[uUgCp]) ]] &&
((i++))
done
case "$prev" in
--user | --other-user | -!(-*)[uU])
COMPREPLY=($(compgen -u -- "$cur"))
return
;;
--group | -!(-*)g)
COMPREPLY=($(compgen -g -- "$cur"))
return
;;
--close-from | --prompt | -!(-*)[Cp])
return
;;
esac
$split && return
if [[ $cur == -* ]]; then
local opts=$(_parse_help "$1")
COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur"))
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
return
fi
if [[ $mode == edit ]]; then
_filedir
fi
} &&
complete -F _sudo sudo sudoedit
# ex: filetype=sh
为了正式回答这个问题,正如@steeldriver 在评论中提到的那样,这是来自项目的completions/sudo
_sudo
文件函数的名称。bash-completion
source
当尝试使用该文件作为参数在 Bash 中使用点或实用程序时,会出现给定的错误消息,并且extglob
未设置选项(这是默认设置¹)。发生这种情况的原因是第 19 行包含扩展模式匹配运算符@()
和!()
:但是,正如@Stéphane Chazelas 指出的那样(见脚注),自 Bash 4.1 以来,扩展模式匹配运算符应该在
[[ ... ]]
右侧工作==
,因此这可能不是问题的真正根源。根据给出的错误消息,有问题的行似乎是第 29 行:类似地,在文件completions/file
!()
中使用:以下是使用来自 OpenBSD 的文件路径的点实用程序的示例用法(其他系统上的具体位置可能有所不同):
类似上述的命令可能包含在其中一个初始化文件中,或者从中调用的脚本中。
该 (已弃用)选项
-
指示 su(1) 将相关用户的 shell(根据注释,Bash)(不带参数,root)作为(交互式)登录 shell 执行。当作为交互式登录 shell 执行时,Bash 会获取/etc/profile,然后按顺序获取以下列表中的第一个现有文件:
对于 root 用户,替换
~
为/root
:连同/etc/profile一起,这些是用于检查文件Completions/sudo来源的文件。一行
应添加到该文件中,在完成/sudo的来源之前。
注意:这可能会影响安全性,因为它允许 root 的 shell 使用扩展的通配符,而扩展的通配符原本是关闭的。
¹@Stéphane Chazelas 的注释:自 bash 4.1
extglob
运算符(ksh 扩展的 glob 运算符的子集)起[[...]]
,无论该选项是否全局启用,都可以在模式匹配运算符中使用。