Linux: Создание rescue-записи grub в Fedora
Для систем, которые существуют очень долго и обновляются через версии есть опасность того, что rescue ядро не заведётся. Вернее оно заведётся, но работать будет некомфортно.
А так как механизма обновления ядра в дефолте нет, то стоит производить его руками хотя бы раз в несколько версий дистрибутива.
$ sudo rm /boot/*rescue*
$ sudo /usr/lib/kernel/install.d/51-dracut-rescue.install add "$(uname -r)" /boot "/boot/vmlinuz-$(uname -r)"
KDE: Dolphin не может создать файл на nfs, а консоль может
Итак. Существует проблема в связке nfs+dolphin. Настолько большая, что многие пользователи попросту не используют nfs.
Она заключается в том, что если на каталоге установлено сопоставление с анонимным пользователем для всех (через all_squash
), то в ряде случаев пользователи просто не могут создавать каталоги и файлы из dolphin (где-то видел упоминание о том, что nautilus так же поломан). Только через консоль (либо альтернативные менеджеры)
Проблема имеет лишь несколько веток на реддите вида Dolphin Can’t Edit Synology NFS Folders Even When User Has Permissions?
Хотя и обычный nfs подвержен таким же проблемам.
Рассматривать будем на примере nas от synology.
Данное явление распространяется как на nfs3, так и на nfs4. Последнюю использовать дома смысла нет - её преимущества раскрываются только в домене.
На записи ниже хорошо видно как проявляет себя проблема.
Казалось бы. Пользователь сопоставляется с админом. На каталоге есть права для пользователя. Что ещё надо?
# cat /etc/exports
/volume1/projects 192.168.1.0/24(rw,async,no_wdelay,all_squash,insecure_locks,sec=sys,anonuid=1024,anongid=100)
$ ls -ld misc/
drwxrwxr-x. 3 nas-writer users 4096 окт 21 23:14 misc/
$ ls -ld misc/Новая\ папка/
drwxr-xr-x. 2 nas-writer users 4096 окт 21 23:18 'misc/Новая папка/'
Попробуем добавить прав как это сделано с родительским каталогом.
$ sudo chmod g+w misc/Новая\ папка/
$ ls -ld misc/Новая\ папка/
drwxrwxr-x. 2 nas-writer users 4096 окт 21 23:18 'misc/Новая папка/'
И опять ничего не выходит:
И даже если добавить права на всех (a+w
), то мы тоже не сможем создавать файлы и каталоги из файлового менеджера.
$ sudo chmod a+w misc/Новая\ папка/
$ ls -ld misc/Новая\ папка/
drwxrwxrwx. 2 nas-writer users 4096 окт 21 23:18 'misc/Новая папка/'
Корни проблемы:
- в первую очередь проблема в KIO и KDE (там есть баг аж от 2015 года).
- во вторую очередь - это чехарда с правами на самой станции (которая иногда случается когда файлы копируются туда-сюда или рсинкаются).
Давайте посмотрим на то, что происходит на станции.
Разрешения папки misc.
И разрешение папки Новая папка
.
Очевидно, что они наследуются. Разрешение на запись для админа выглядит так:
Однако, если мы поставим a+w
на папку misc, то dolphin сможет создавать файлы внутри нового каталога. И мы можем даже убрать права o-w
на новую папку! И всё равно файлы создавать можно.
$ sudo chmod a+w misc
$ ls -ld misc/
drwxrwxrwx. 4 nas-writer users 4096 окт 21 23:18 misc/
$ sudo chmod o-w misc/Новая\ папка/
$ ls -ld misc/Новая\ папка/
drwxrwxr-x. 2 nas-writer users 4096 окт 21 23:18 'misc/Новая папка/'
И я даже знать не хочу почему это работает.
Теперь мы можем всё починить. Так как при создании папок права наследуются от родительского объекта, то нам нужно для группы администраторов (а в данном случае это именно так и есть) дать полный доступ на родительский каталог и на все существующие в данным момент папки.
Для этого установим администраторов единственной группой с полным доступом к файлам.
Для этого в файловом менеджере на станции выбираем экспортируемый каталог и на вкладке разрешений устанавливаем следующие права.
Обязательно выставляем флажок для применения ко вложенным объектам.
Стоит отметить еще один эффект: теперь все файлы и папки создаются с правами 777.
Даже если они создаются через smb-шару.
Речь идет только о шарах с полным доступом для всех пользователей. Т.н. файлопомойки. Задача таких мест - это позволять любому пользователю писать и удалять любые объекты. В статье мы не рассматриваем случай с авторизованными пользователями - там всё и так хорошо.
Вообще стоит объяснить почему так происходит.
В данном случае применяется не обычные права доступа, а расширенный acl. Он настраивается таким образом, что дочерние объекты наследуют пермиссии родительских.
Давайте посмотрим на примере.
$ mkdir test
$ ls -la
итого 0
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:11 .
drwx------. 1 penguin penguin 810 окт 22 00:05 ..
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:11 test
$ cd test/
$ mkdir test_2
$ ls -la
итого 0
drwxr-xr-x. 1 penguin penguin 12 окт 22 00:11 .
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:11 ..
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:11 test_2
$ cd ..
$ chmod g+w test/
$ cd test/
$ mkdir test_3
$ ls -la
итого 0
drwxrwxr-x. 1 penguin penguin 24 окт 22 00:11 .
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:11 ..
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:11 test_2
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:11 test_3
Видим, что изменение прав на родительский каталог никак не повлияло на создание дочернего каталога test_3
. Потому что права подчиняются установленной в система umask
, dmask
и fmask
.
А теперь то же самое, но с acl.
$ mkdir test
$ ls -la
итого 0
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:16 .
drwx------. 1 penguin penguin 810 окт 22 00:05 ..
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:16 test
$ cd test/
$ mkdir test_2
$ ls -la
итого 0
drwxr-xr-x. 1 penguin penguin 12 окт 22 00:16 .
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:16 ..
drwxr-xr-x. 1 penguin penguin 0 окт 22 00:16 test_2
$ cd ../
$ setfacl --recursive --modify u:penguin:rwX,g:penguin:rwX,d:g:penguin:rwX,d:u:penguin:rwX test
$ ls -la
итого 0
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:16 .
drwx------. 1 penguin penguin 810 окт 22 00:05 ..
drwxrwxr-x+ 1 penguin penguin 12 окт 22 00:16 test
$ getfacl test/
# file: test/
# owner: penguin
# group: penguin
user::rwx
user:penguin:rwx
group::r-x
group:penguin:rwx
mask::rwx
other::r-x
default:user::rwx
default:user:penguin:rwx
default:group::r-x
default:group:penguin:rwx
default:mask::rwx
default:other::r-x
$ cd test/
$ ls -la
итого 0
drwxrwxr-x+ 1 penguin penguin 12 окт 22 00:16 .
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:16 ..
drwxrwxr-x+ 1 penguin penguin 0 окт 22 00:16 test_2
$ mkdir test_3
$ ls -la
итого 0
drwxrwxr-x+ 1 penguin penguin 24 окт 22 00:18 .
drwxr-xr-x. 1 penguin penguin 8 окт 22 00:16 ..
drwxrwxr-x+ 1 penguin penguin 0 окт 22 00:16 test_2
drwxrwxr-x+ 1 penguin penguin 0 окт 22 00:18 test_3
В этом и кроется способ починки nfs и dolphin.
И еще стоит обратить внимание, что acl для nfs4 отличается. И именно поэтому стоит использовать nfs3 если у вас нет домена.
Python: парсим аргументы командной строки
Сегодня разберемся с сабпарсерами объекта argparse.ArgumentParser
, которые передаются через параметр parents
.
В общем случае при попытке распарсить аргументы командной строки мы создаем объект и начинаем методично добавлять к нему все известные нам параметры.
Иногда можно встретить очень большие листинги. Но существует механизм, который позволяет разбивать парсеры на более мелкие составляющие и сцеплять их между собой для более простого понимания (кстати, очень полезно при создании системы плагинов).
При этом мы можем управлять тем, какие аргументы будут парсится.
Для этого в параметры parents
можно передать те объекты, от которых надо унаследоваться.
Рассмотрим на примерах.
В первом случае создается ArgumentParser
с одним аргументом. И он сразу же разбирает командную строку на известные параметры и хвост при помощи parse_known_args
.
В зависимости от значения -l
мы либо продолжим работу, либо остановимся.
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-l', '--list', help="List something", action='store_true')
args, remaining = parser.parse_known_args()
if args.list:
print('List')
exit(0)
parser = argparse.ArgumentParser(
description="Chained parsers",
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parser])
parser.add_argument('-t', '--test', help="Test", action='store_true')
other_args = parser.parse_args(remaining)
print('Args: {}'.format(other_args))
Второй пример чуть более сложный.
Допустим, что код обрабатывает видеофайлы и аудиофайлы. В зависимости от этого у него меняется поведение атрибута -r
.
import argparse
import enum
class Formats(enum.Enum):
VIDEO='video'
AUDIO='audio'
def __str__(self):
return self.value
def parser_common():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
'-f', '--format', help="Specify format", type=Formats, choices=list(Formats)
)
return parser
def parser_video(parent_parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Video parser",
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parent_parser])
parser.add_argument(
'-r',
'--resolution',
help="Resolution",
type=int,
nargs=2,
metavar=('WIDTH', 'HEIGHT'),
required=True,
)
return parser
def parser_audio(parent_parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Audio parser",
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parent_parser])
parser.add_argument(
'-r',
'--resolution',
help="Audit resolution",
type=int,
required=True,
)
return parser
def main():
parser = parser_common()
args, remaining = parser.parse_known_args()
if args.format == Formats.AUDIO:
parser = parser_audio(parser)
elif args.format == Formats.VIDEO:
parser = parser_video(parser)
else:
parser.print_help()
exit(1)
other_args = parser.parse_args(remaining)
print(2)
print('Args: {}'.format(other_args))
if __name__ == '__main__':
main()
Запустите и посмотрите, как ведёт себя данный код.
$ python argsparser.py
usage: argsparser.py [-f {video,audio}]
options:
-f {video,audio}, --format {video,audio}
Specify format
$ python argsparser.py -f audio
usage: argsparser.py [-h] [-f {video,audio}] -r RESOLUTION
argsparser.py: error: the following arguments are required: -r/--resolution
$ python argsparser.py -f video
usage: argsparser.py [-h] [-f {video,audio}] -r WIDTH HEIGHT
argsparser.py: error: the following arguments are required: -r/--resolution
$ python argsparser.py -f video -h
usage: argsparser.py [-h] [-f {video,audio}] -r WIDTH HEIGHT
Video parser
options:
-h, --help show this help message and exit
-f {video,audio}, --format {video,audio}
Specify format
-r WIDTH HEIGHT, --resolution WIDTH HEIGHT
Resolution
$ python argsparser.py -f audio -h
usage: argsparser.py [-h] [-f {video,audio}] -r RESOLUTION
Audio parser
options:
-h, --help show this help message and exit
-f {video,audio}, --format {video,audio}
Specify format
-r RESOLUTION, --resolution RESOLUTION
Audit resolution
SDDM: Переключаем раскладку автоматически при блокировании экрана
Продолжаем разбираться с окном логина (sddm, gdm и прочие *dm).
В предудущей части мы научились переключать раскладку из консоли минуя кнопки и мышки.
А теперь мы научимся менять раскладку автоматически при блокировании экрана.
Зачем это нужно? Чаще всего пароль у нас на латинице. А заблокировать экран можно при любой включенной раскладке. Это приводит к тому, что на экране логина эту самую раскладку на до менать. Неудобно!
1. Определяем, когда система была заблокирована
#!/usr/bin/env bash
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" |
while read x; do
case "$x" in
*"boolean true"*) echo SCREEN_LOCKED;;
*"boolean false"*) echo SCREEN_UNLOCKED;;
esac
done
Если запустить скрипт, заблокировать, а потом разблокировать экран, то мы увидим его работу.
SCREEN_LOCKED
SCREEN_LOCKED
SCREEN_UNLOCKED
SCREEN_UNLOCKED
Два сообщения из-за особенностей интерфейса. Можно привязываться к другому интерфейсу, но в данном случае это некритично.
2. Учимся запускать скрипт фоном через systemd
Делаем скрипт /.local/bin/set-layout-on-lock
. Не забывайте поставить на него `+x .
#!/usr/bin/env bash
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" |
while read x; do
case "$x" in
*"boolean true"*) qdbus org.kde.keyboard /Layouts org.kde.KeyboardLayouts.setLayout 0;;
*"boolean false"*) echo SCREEN_UNLOCKED;;
esac
done
Создаём каталог для сервисов systemd.
$ mkdir -p ${HOME}/.config/systemd/user
Пишем сервис в ${HOME}/.config/systemd/user/set-kbd-layout-on-lock.service
.
[Unit]
Description=Set custom locale on screen lock
[Service]
Restart=always
ExecStart=%h/.local/bin/set-layout-on-lock
[Install]
WantedBy=graphical-session.target
%h
- означает директорию текущего пользователя.graphical-session.target
- означает, что сервис будет запускаться только с графическим интерфейсом (не нужен он нам в консоли).
3. Включаем
$ systemctl --user enable --now set-kbd-layout-on-lock
Сервис будет включен и тут же запущен.
Посмотреть состояние можно командой status
.
$ systemctl --user status set-kbd-layout-on-lock
Литература
KDE: Переключаем раскладку из консоли
Очень полезной штукой является возможность переключить раскладку из консоли.
Зачем? Например, при блокировании сеанса надо сделать так, чтобы раскладка стала английской.
Так как дистрибутивы очень сильно видоизменились и стали поставляться с wayland и производными systemd (keyboad, logind, …), то переключать стандартными линуксовыми средствами вроде setxkbmap, xkb-switch и прочими способами не получиться.
Теперь раскладка в дистрибутивах переключается при помощи dbus и сигналов.
Для kde это делается вызовом метода org.kde.KeyboardLayouts.setLayout
в сервисе org.kde.keyboard
.
$ qdbus org.kde.keyboard /Layouts org.kde.KeyboardLayouts.setLayout 1
Последний аргумент - это номер раскладки в списке.
Посмотреть список раскладок можно через другой метод.
$ qdbus --literal org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayoutsList
[Argument: a(sss) {[Argument: (sss) "us", "", "Английская (США)"], [Argument: (sss) "ru", "", "Русская"]}]
Обязательный аргумент в нашем случае - это --literal
. Без него команда просто выведет сообщение о том, что не может отобразить нестандарный тип данных.
$ qdbus org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayoutsList
qdbus: I don't know how to display an argument of type 'a(sss)', run with --literal.