С тех пор как я деактивировал bt_coex, проблема для меня решена. Если я не подключаю мышь слишком быстро после пробуждения из режима ожидания (т.е.: жду, пока установится WiFi), все работает нормально.
Эскейпирование специальных символов — непростая задача. Вместо этого вы можете сначала выбрать поле имени пользователя из вывода getent
, а затем сопоставить с полной оставшейся строкой:
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
fi
getent passwd | cut -d: -f1 | grep -xF -e "$user"
-F
для фиксированных строк, -x
для полного соответствия строки.
Если у вас нет пользователей с именами, состоящими только из цифр, вы можете использовать getent
:
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
elif [[ $user =~ ^[0-9]+$ ]] ; then
echo "Cannot handle username of digits only, sorry :("
continue
fi
if ! getent -- passwd "$user" > /dev/null ; then
echo "$user doesn't exist"
continue
fi
Или, чтобы избежать проблем с getent
или другими, предполагающими строку цифр должен быть UID вместо имени пользователя, мы должны вызвать getpwnam()
вручную. Это не делает других предположений о том, какими могут быть имена пользователей, кроме того, что делает базовая реализация getpwnam()
.
export user
if ! perl -e 'exit !defined getpwnam($ENV{user})' ; then
echo "$user doesn't exist"
fi
Я не буду писать соответствующую оболочку C.
Либо экранируйте его, либо поместите его в класс символов, что-то в этом роде:
grep '\['
grep '[[]'
grep -e "${user//\[/\\\[}"
Синтаксис ${var//c/d}
=> в переменной оболочки $var
заменяем все символы c
на d
. Теперь в вашем случае c
— это [
, но так получилось, что [
является особенным в этом синтаксисе (оно делает подстановку), и, следовательно, нам нужно его избежать поставив перед ним обратную косую черту, т. е. \[
.
Теперь перейдем к запасной части. Нам нужен \[
. Но опять же, и \
, и [
являются специальными в этом синтаксисе подстановки параметров ${var//...}
и, следовательно, оба должны быть, да вы правильно догадались, косая черта
приводя к выражению: \\\[
: "${var//\[/\\\[}"
HTH
[
— не единственный символ, который экранируется для регулярных выражений. Все операторы RE включают .
, который часто встречается в именах пользователей (например, r.ot
, поскольку регулярное выражение соответствует root
).
Кроме того, ваш подход (getent passwd | grep "^$user:"
) также недействителен в том смысле, что он не будет помечать root:0
как недействительный, например.
Здесь было бы лучше использовать awk
:
user_valid() {
getent passwd |
U="$1" awk -F: '$1 == ENVIRON["U"] {found = 1; exit}
END {exit(1 - found)}'
}
Теперь не все пользовательские базы данных позволяют такое перечисление.
$ getent passwd | grep stephane
$ id -u stephane
10631
$ getent passwd stephane
stephane:*:10631:10631:Stephane Chazelas:/export/./home/stephane:/bin/zsh
В моем случае этот пользователь находится в базе данных LDAP. перечисление отключено (могут быть тысячи пользователей), но я все еще могу запрашивать/разрешать пользователей по отдельности.
Итак, здесь, чтобы проверить пользователей, лучше запросить базу данных пользователей непосредственно для этого пользователя. Например, с помощью команды id
(стандартная команда, противоречащая getent
):
user_valid() {
case $1 in
(*[!0-9]*) id -u -- "$1" > /dev/null 2>&1;;
(*) false;;
esac
}
(все цифры пользователей рассматриваются отдельно как некоторый id
дадут вам информацию для идентификатора пользователя в этом случае Имена пользователей не могут быть числовыми в большинстве систем (это нарушит большинство команд, которые ожидают либо имена пользователей, либо идентификаторы пользователей в качестве аргументов (например, id
s выше, ps
, найти
...))).