Skip to content

Руководство по разработке модулей ​

ShizuSU предоставляет механизм модулей, позволяющий добиться эффекта модификации системного каталога при сохранении целостности системного раздела. Этот механизм принято называть "бессистемным".

Модульный механизм ShizuSU практически аналогичен механизму Magisk. Если вы знакомы с разработкой модулей Magisk, то разработка модулей ShizuSU очень похожа. Представление модулей ниже можно пропустить, достаточно прочитать [различия-с-magisk] (difference-with-magisk.md).

МЕТАМОДУЛЬ ТРЕБУЕТСЯ ТОЛЬКО ДЛЯ МОДИФИКАЦИИ СИСТЕМНЫХ ФАЙЛОВ

Модульная система ShizuSU основана на Magic Mount (из SukiSU-Ultra); для монтирования директории system не требуется устанавливать metamodule. Модули, изменяющие файлы /system, работают из коробки. См. Модульная система: Magic Mount.

Ядерные модули KPM ​

KernelPatch Module (KPM) позволяет загружать модули непосредственно на уровне ядра — идеально для продвинутых модификаций и улучшений ядра. ShizuSU полностью поддерживает KPM (портировано из Apatch). Для использования KPM включите CONFIG_KPM=y при сборке ядра.

WebUI ​

ShizuSU modules support displaying interfaces and interacting with users. See the WebUI documentation for additional details.

Конфигурация модулей ​

ShizuSU предоставляет встроенную систему конфигурации, которая позволяет модулям хранить постоянные или временные настройки в формате ключ-значение. Подробности смотрите в документации по конфигурации модулей.

Busybox ​

В комплект поставки ShizuSU входит полнофункциональный бинарный файл BusyBox (включая полную поддержку SELinux). Исполняемый файл находится по адресу /data/adb/ksu/bin/busybox. BusyBox от ShizuSU поддерживает переключаемый во время работы "ASH Standalone Shell Mode". Этот автономный режим означает, что при запуске в оболочке ash BusyBox каждая команда будет напрямую использовать апплет внутри BusyBox, независимо от того, что задано в качестве PATH. Например, такие команды, как ls, rm, chmod будут НЕ использовать то, что находится в PATH (в случае Android по умолчанию это будут /system/bin/ls, /system/bin/rm и /system/bin/chmod соответственно), а вместо этого будут напрямую вызывать внутренние апплеты BusyBox. Это гарантирует, что скрипты всегда будут выполняться в предсказуемом окружении и всегда будут иметь полный набор команд, независимо от того, на какой версии Android они выполняются. Чтобы заставить команду не использовать BusyBox, необходимо вызвать исполняемый файл с полными путями.

Каждый сценарий оболочки, запущенный в контексте ShizuSU, будет выполняться в оболочке BusyBox ash с включенным автономным режимом. Для сторонних разработчиков это касается всех загрузочных скриптов и скриптов установки модулей.

Для тех, кто хочет использовать эту возможность "Автономного режима" вне ShizuSU, есть два способа включить ее:

  1. Установите переменной окружения ASH_STANDALONE значение 1
    Пример: ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script>
  2. Переключитесь с помощью параметров командной строки:
    /data/adb/ksu/bin/busybox sh -o standalone <script>

Чтобы убедиться, что все последующие запуски оболочки sh также выполняются в автономном режиме, предпочтительным методом является вариант 1 (и это то, что ShizuSU и менеджер ShizuSU используют внутри), поскольку переменные окружения наследуются вплоть до дочерних процессов.

отличие от Magisk

BusyBox в ShizuSU теперь использует бинарный файл, скомпилированный непосредственно из проекта Magisk. **Поэтому вам не нужно беспокоиться о проблемах совместимости между скриптами BusyBox в Magisk и ShizuSU, поскольку они абсолютно одинаковы!

Модули ShizuSU ​

Модуль ShizuSU - это папка, размещенная в каталоге /data/adb/modules и имеющая следующую структуру:

txt
/data/adb/modules
├── .
├── .
|
├── $MODID                  <--- Папка имеет имя с идентификатором модуля
│   │
│   │      *** Идентификация модуля ***
│   │
│   ├── module.prop         <--- В этом файле хранятся метаданные модуля
│   │
│   │      *** Основное содержимое ***
│   │
│   ├── system              <--- Эта папка будет смонтирована, если skip_mount не существует
│   │   ├── ...
│   │   ├── ...
│   │   └── ...
│   │
│   │      *** Флаги состояния ***
│   │
│   ├── skip_mount          <--- Если он существует, то ShizuSU НЕ будет монтировать вашу системную папку
│   ├── disable             <--- Если модуль существует, то он будет отключен
│   ├── remove              <--- Если модуль существует, то при следующей перезагрузке он будет удален
│   │
│   │      *** Необязательные файлы ***
│   │
│   ├── post-fs-data.sh     <--- Этот скрипт будет выполняться в post-fs-data
│   ├── service.sh          <--- Этот скрипт будет выполняться в сервисе late_start
|   ├── uninstall.sh        <--- Этот скрипт будет выполнен, когда ShizuSU удалит ваш модуль
│   ├── system.prop         <--- Свойства из этого файла будут загружены в качестве системных свойств программой resetprop
│   ├── sepolicy.rule       <--- Дополнительные пользовательские правила sepolicy
│   ├── initrc/             <--- Файлы .rc в этом каталоге будут добавлены в init.rc при загрузке
│   │   ├── myservice.rc
│   │   └── ...
│   │
│   │      *** Автоматически генерируется, НЕЛЬЗЯ создавать или изменять вручную ***
│   │
│   ├── vendor              <--- Символьная ссылка на $MODID/system/vendor
│   ├── product             <--- Символьная ссылка на $MODID/system/product
│   ├── system_ext          <--- Симлинк на $MODID/system/system_ext
│   │
│   │      *** Допускается использование любых дополнительных файлов/папок ***
│   │
│   ├── ...
│   └── ...
|
├── another_module
│   ├── .
│   └── .
├── .
├── .

различия с Magisk

ShizuSU не имеет встроенной поддержки Zygisk, поэтому в модуле нет содержимого, связанного с Zygisk. Однако для поддержки модулей Zygisk можно использовать ZygiskNext. В этом случае содержимое модуля Zygisk идентично содержимому, поддерживаемому Magisk.

module.prop ​

module.prop - это конфигурационный файл модуля. В ShizuSU, если модуль не содержит этого файла, он не будет распознан как модуль. Формат этого файла следующий:

txt
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
updateJson=<url> (optional)
actionIcon=<path> (optional)
webuiIcon=<path> (optional)
  • id должно соответствовать данному регулярному выражению: ^[a-zA-Z][a-zA-Z0-9._-]+$
    экс: ✓ a_module, ✓ a.module, ✓ module-101, ✗ a module, ✗ 1_module, ✗ -a-module
    Это уникальный идентификатор вашего модуля. Не следует изменять его после публикации.
  • versionCode должен быть целым. Это используется для сравнения версий.
  • Другими, не упомянутыми выше, могут быть любые однострочные строки.
  • Обязательно используйте тип перевода строки UNIX (LF), а не Windows (CR+LF) или Macintosh (CR).
  • actionIcon и webuiIcon — необязательные пути к изображениям, которые используются как значки по умолчанию для ярлыков действия и WebUI модуля в менеджере. Эти пути должны быть относительными к корневому каталогу модуля. Например, actionIcon=icon/icon.png будет интерпретирован как <MODDIR>/icon/icon.png.

ДИНАМИЧЕСКОЕ ОПИСАНИЕ

Поле description может быть динамически переопределено во время выполнения с помощью системы конфигурации модулей. Подробности см. в разделе Переопределение описания модуля.

Сценарии командной оболочки ​

Чтобы понять разницу между post-fs-data.sh и Service.sh, прочитайте раздел Boot Scripts. Для большинства разработчиков модулей service.sh должно быть достаточно, если вам нужно просто запустить загрузочный скрипт.

Во всех скриптах вашего модуля используйте MODDIR=${0%/*} для получения пути к базовому каталогу вашего модуля; НЕ кодируйте жестко путь к вашему модулю в скриптах.

различия с Magisk

С помощью переменной окружения KSU можно определить, выполняется ли сценарий в ShizuSU или в Magisk. Если скрипт выполняется в ShizuSU, то это значение будет равно true.

каталог system ​

После загрузки системы содержимое этого каталога будет наложено поверх раздела /system. Это означает, что:

ТРЕБОВАНИЕ МЕТАМОДУЛЯ

Модульная система ShizuSU основана на Magic Mount (из SukiSU-Ultra); каталог system монтируется напрямую без метамодуля. См. Модульная система: Magic Mount.

  1. Файлы с теми же именами, что и в соответствующем каталоге в системе, будут перезаписаны файлами в этом каталоге.
  2. Папки с теми же именами, что и в соответствующем каталоге в системе, будут объединены с папками в этом каталоге.

Если вы хотите удалить файл или папку в исходном каталоге системы, объявите в customize.sh переменную REMOVE, содержащую список каталогов. ShizuSU скроет эти файлы через Magic Mount (раздел /system при этом фактически не изменится).

sh
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"

/system/app/YouTube и /system/app/Bloatware будут скрыты после вступления модуля в силу.

Если вы хотите заменить каталог в системе, объявите переменную REPLACE в customize.sh. ShizuSU выполнит bind mount пустого каталога поверх целевого пути, полностью заменив его (без изменения раздела /system).

sh
REPLACE="
/system/app/YouTube
/system/app/Bloatware
"

/system/app/YouTube и /system/app/Bloatware будут заменены на пустые каталоги после вступления модуля в силу.

различия с Magisk

Официальный KernelSU использует механизм OverlayFS (metamodule) для бессистемных модификаций, тогда как ShizuSU, основанный на SukiSU-Ultra, использует Magic Mount (bind mount), как и Magisk. Оба подхода достигают одной цели: модификация файлов /system без физического изменения раздела /system. ShizuSU использует только Magic Mount — двух модульных систем не существует. См. Модульная система: Magic Mount.

system.prop ​

Этот файл имеет тот же формат, что и build.prop. Каждая строка состоит из [key]=[value].

sepolicy.rule ​

Если для вашего модуля требуются дополнительные патчи sepolicy, добавьте эти правила в данный файл. Каждая строка в этом файле будет рассматриваться как утверждение политики.

Инъекция initrc ​

ShizuSU предоставляет механизм для внедрения кастомных директив Android Init RC в системный init.rc. Это позволяет модулям регистрировать кастомные службы Android, устанавливать триггеры свойств или выполнять другие действия на языке Init без изменения системного раздела.

Во время загрузки модуль ядра ShizuSU перехватывает системные вызовы read() и fstat(). Когда процесс init Android читает /system/etc/init/hw/init.rc, ShizuSU прозрачно добавляет кастомное содержимое RC в конец файла. Процесс init анализирует эти внедренные директивы точно так же, как исходное содержимое init.rc.

На стороне пользовательского пространства ksud объединяет все файлы .rc из включенных модулей в один файл modules.rc, хранящийся в разделе /metadata. Этот файл автоматически пересоздается всякий раз, когда изменяется состояние модуля (установка, включение, отключение, удаление и т.д.).

Файлы initrc модуля ​

Создайте подкаталог initrc/ в каталоге вашего модуля и поместите туда файлы .rc:

txt
/data/adb/modules/<MODID>/
├── initrc/
│   ├── myservice.rc
│   └── another.rc
└── ...

TIP

  • Файлы должны иметь расширение .rc.
  • Пока модуль включен, все файлы .rc в каталоге initrc/ будут включены (разрешение на выполнение не требуется).
  • Файлы обрабатываются в алфавитном порядке имен файлов внутри каталога, а модули обрабатываются в алфавитном порядке ID модулей.

Общие файлы initrc ​

Помимо файлов RC на уровне модуля, вы можете поместить файлы .rc в глобальный каталог:

txt
/data/adb/initrc.d/
├── myservice.rc
└── another.rc

Общим файлам initrc требуется разрешение на выполнение

В отличие от каталога модуля initrc/, файлы в /data/adb/initrc.d/ должны иметь права на выполнение, чтобы быть включенными. Неисполняемые файлы .rc будут пропущены без уведомления.

Общие файлы initrc.d/ обрабатываются до любых файлов RC модулей.

Пример ​

Вот пример файла .rc, который регистрирует кастомную службу Android:

rc
service myservice /data/adb/modules/mymodule/bin/myservice
    user root
    group root
    disabled
    seclabel u:r:ksu:s0

on property:sys.boot_completed=1
    start myservice

Если этот файл помещен в /data/adb/modules/mymodule/initrc/myservice.rc, он зарегистрирует службу с именем myservice при загрузке и запустит ее по достижении sys.boot_completed=1.

Обновление вручную ​

Вы можете вручную запустить пересоздание modules.rc с помощью следующей команды (изменения вступят в силу при следующей загрузке):

sh
ksud initrc refresh

TIP

  • Инъекция initrc происходит очень рано в процессе загрузки (когда init читает init.rc), до выполнения post-fs-data и любых скриптов модуля.
  • Внедренное содержимое RC рассматривается init как часть исходного init.rc, поддерживая весь синтаксис языка Android Init (определения служб, триггеры, настройки свойств и т.д.).
  • Инъекция initrc недоступна в режиме late-load, поскольку хуки системных вызовов в этом режиме не устанавливаются.
  • Инъекцию RC модулей можно отключить, передав параметр --no-custom-rc при патчинге образа с помощью ksud.

Установщик модулей ​

Инсталлятор модуля ShizuSU - это модуль ShizuSU, упакованный в zip-файл, который может быть прошит в APP-менеджере ShizuSU. Простейший установщик модуля ShizuSU - это просто модуль ShizuSU, упакованный в zip-файл.

txt
module.zip
│
├── customize.sh                       <--- (Необязательно, более подробно позже)
│                                           Этот скрипт будет использоваться в update-binary
├── ...
├── ...  /* Остальные файлы модуля */
│

WARNING

Модуль ShizuSU НЕ поддерживается для установки в пользовательское Recovery!!!

Персонализация ​

Если вам необходимо настроить процесс установки модуля, то в качестве опции вы можете создать в программе установки скрипт с именем customize.sh. Этот скрипт будет источником (не исполняться!) сценария установщика модуля после извлечения всех файлов и применения стандартных разрешений и secontext. Это очень удобно, если ваш модуль требует дополнительной настройки в зависимости от ABI устройства, или вам необходимо установить специальные разрешения/секонтекст для некоторых файлов модуля.

Если вы хотите полностью контролировать и настраивать процесс установки, объявите SKIPUNZIP=1 в файле customize.sh, чтобы пропустить все шаги установки по умолчанию. При этом ваш customize.sh будет сам отвечать за установку.

Сценарий customize.sh запускается в оболочке BusyBox ash ShizuSU с включенным "Автономным режимом". Доступны следующие переменные и функции:

Переменные ​

  • KSU (bool): переменная, отмечающая, что скрипт выполняется в окружении ShizuSU, причем значение этой переменной всегда будет true. Ее можно использовать для различения ShizuSU и Magisk.
  • KSU_VER (string): строка версии текущего установленного ShizuSU (например, v0.4.0)
  • KSU_VER_CODE (int): код версии текущего установленного ShizuSU в пользовательском пространстве (например, 10672)
  • KSU_KERNEL_VER_CODE (int): код версии текущей установленной ShizuSU в пространстве ядра (например, 10672)
  • BOOTMODE (bool): в ShizuSU всегда должно быть true.
  • MODPATH (path): путь, по которому должны быть установлены файлы ваших модулей
  • TMPDIR (path): место, где вы можете временно хранить файлы
  • ZIPFILE (path): установочный zip-архив вашего модуля
  • ARCH (string): архитектура процессора устройства. Значение: arm, arm64, x86 или x64.
  • IS64BIT (bool): true, если $ARCH имеет значение arm64 или x64.
  • API (int): уровень API (версия Android) устройства (например, 23 для Android 6.0)
  • KSU_UAPI_VER (int): версия UAPI пользовательского пространства ShizuSU (ksud) (например, 2). Эта версия увеличивается при критических изменениях в драйвере ядра, и модули могут использовать её для проверки совместимости.
  • KSU_RUNTIME_MODE (string): текущий режим работы ShizuSU. Возможные значения: built-in (режим GKI, встроен в ядро), lkm (загружен как модуль ядра при запуске) или late-load (загружен как модуль ядра после загрузки).
  • KSU_LATE_LOAD (int?): если ShizuSU загружен с задержкой после загрузки системы, значение этой переменной равно 1; в противном случае переменная не устанавливается.

WARNING

В ShizuSU MAGISK_VER_CODE всегда равен 25200, а MAGISK_VER всегда равен v25.2. Пожалуйста, не используйте эти две переменные для определения того, запущен ли он на ShizuSU или нет.

Функции ​

txt
ui_print <msg>
    вывести <msg> на консоль
    Избегайте использования 'echo', так как он не будет отображаться в консоли пользовательского recovery

abort <msg>
    вывести сообщение об ошибке <msg> на консоль и завершить установку
    Избегайте использования команды 'exit', так как в этом случае будут пропущены шаги очистки завершения установки

set_perm <target> <owner> <group> <permission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    Эта функция является сокращением для следующих команд:
       chown owner.group target
       chmod permission target
       chcon context target

set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    для всех файлов в <directory> будет вызвана команда:
       set_perm file owner group filepermission context
    для всех каталогов в <directory> (включая себя самого), он вызовет:
       set_perm dir owner group dirpermission context

Загрузочные сценарии ​

В ShizuSU скрипты делятся на два типа в зависимости от режима их работы: режим post-fs-data и режим late_start service:

  • режим post-fs-data
    • Эта стадия является БЛОКИРУЮЩЕЙ. Процесс загрузки приостанавливается до завершения выполнения или по истечении 10 секунд.
    • Сценарии запускаются до того, как будут смонтированы какие-либо модули. Это позволяет разработчику модулей динамически настраивать свои модули до того, как они будут смонтированы.
    • Этот этап происходит до запуска Zygote, что практически означает, что все в Android
    • ПРЕДУПРЕЖДЕНИЕ: использование setprop приведет к блокировке процесса загрузки! Вместо этого используйте resetprop -n <prop_name> <prop_value>.
    • Запускайте скрипты в этом режиме только в случае необходимости.
  • режим обслуживания late_start
    • Эта стадия является НЕБЛОКИРУЮЩЕЙ. Ваш скрипт выполняется параллельно с остальным процессом загрузки.
    • Это рекомендуемый этап для запуска большинства скриптов.

В ShizuSU скрипты запуска делятся на два типа по месту их хранения: общие скрипты и скрипты модулей:

  • Общие скрипты
    • Размещаются в файлах /data/adb/post-fs-data.d или /data/adb/service.d.
    • Выполняется только в том случае, если скрипт установлен как исполняемый (chmod +x script.sh)
    • Скрипты в post-fs-data.d выполняются в режиме post-fs-data, а скрипты в service.d - в режиме late_start service.
    • Модули не должны НЕ добавлять общие скрипты при установке
  • Скрипты модуля
    • Размещаются в отдельной папке модуля
    • Выполняются только в том случае, если модуль включен
    • post-fs-data.sh запускается в режиме post-fs-data, а service.sh - в режиме late_start service.

Все загрузочные скрипты будут выполняться в оболочке BusyBox ash от ShizuSU с включенным "Автономным режимом".

Режим late-load ​

Помимо стандартного процесса загрузки, описанного выше, ShizuSU поддерживает режим late-load для сценариев LKM (загружаемый модуль ядра). В этом режиме модуль ядра ShizuSU загружается после полной загрузки системы, а не во время процесса init.

Когда происходит late-load? ​

Late-load запускается командой ksud late-load. Эта команда:

  1. Определяет текущую версию KMI и загружает соответствующий kernelsu.ko из встроенных ресурсов.
  2. Выполняет инициализацию модуля (правила SELinux, список разрешений, функции и т.д.), которая обычно происходит во время загрузки.

Поскольку система уже полностью запущена, некоторые механизмы времени загрузки недоступны или не нужны.

Отличия от стандартной загрузки ​

ПоведениеСтандартная загрузкаРежим late-load
Модуль ядра загружен init (PID 1)ДаНет (загружен после загрузки)
Хуки kprobe ksud (execve/read/fstat/input)ДаПропущены
Обнаружение безопасного режима (клавиша громкости)ДаВсегда отключено
Захват журнала загрузки (logcat/dmesg)ДаПропущен
Проверка сосуществования с MagiskДаПропущена
Событие post-fs-data отправлено ядруДаПропущено
Событие boot-completed отправлено ядруДаУстановлено напрямую при инициализации
Скрипты post-fs-data.sh / post-fs-data.d/ДаЗаменены этапом late-load
Загрузка system.propДаДа
Монтирование модулей Magic MountДаДа
Скрипты post-mount.sh / post-mount.d/ДаДа
Скрипты service.sh / service.d/ДаДа
Скрипты boot-completed.sh / boot-completed.d/ДаДа
Переменная окружения KSU_LATE_LOADНе установленаУстановлена в 1
Флаг info ядра 0x4Не установленУстановлен

Порядок выполнения скриптов ​

В режиме late-load порядок выполнения скриптов следующий:

txt
ksud late-load:
  1. Загрузить kernelsu.ko (если ещё не загружен)
  2. Извлечь бинарные файлы, обработать обновления модулей, загрузить правила SELinux, инициализировать функции
  3. Выполнить скрипты late-load.d/ и скрипты late-load модулей (блокирующе)
  4. Загрузить system.prop (resetprop -n)
  5. Выполнить монтирование модулей Magic Mount
  6. Выполнить скрипты post-mount.d/ и post-mount.sh модулей (блокирующе)
  7. Выполнить скрипты service.d/ и service.sh модулей (неблокирующе)
  8. Выполнить скрипты boot-completed.d/ и boot-completed.sh модулей (неблокирующе)

Скрипты, специфичные для late-load ​

Модули могут предоставить скрипт late-load.sh, который выполняется только в режиме late-load, как замена post-fs-data.sh. Этот скрипт выполняется до монтирования модулей, аналогично post-fs-data.sh в стандартном потоке.

Кроме того, общие скрипты можно размещать в /data/adb/late-load.d/ для выполнения на этом этапе.

Обнаружение режима late-load в скриптах ​

Модули могут определить режим late-load, проверив переменную окружения KSU_LATE_LOAD:

sh
if [ "$KSU_LATE_LOAD" = "1" ]; then
    # Работа в режиме late-load
    echo "Late-load mode detected"
fi

Это позволяет модулям соответствующим образом корректировать своё поведение, например, пропуская операции, необходимые только при ранней загрузке.

Удобство управления модулями ​

ShizuSU предоставляет ряд удобств управления модулями:

  • Резервное копирование и восстановление:Бэкап/восстановление установленных модулей и белого списка root в один тап.
  • Пакетная установка:Установка нескольких zip-модулей за раз; сбой одного модуля не прерывает процесс, ошибки собираются и сообщаются в конце.
  • Пакетное управление:Включение, отключение, отключение всех и удаление всех в один тап.

Выпускается под лицензией GPL3.