In this post I summarize everything I found out about using Magisk (https://topjohnwu.github.io/Magisk) until now. A lot of the infos in this post are already in my other posts in this board but hopefully this summary is useful anyway.
My main purpose is to configure Magisk as much as possible via scripts so this tutorial is mostly about using Magisk via CLI commands in an adb shell or from within scripts.
Please note that I mirror all my HowTos for Android on my web page:
http://bnsmb.de/My_HowTos_for_Android.html
I will update this post when I found something new and interesting. A history of changes in this post is at the end of the post.
PreRequisites
Most of the instructions below need an enabled adb access for the phone and root permissions for the adb shell. In addition, a working Recovery image that is able to mount the /data partition (like for example TWRP) is strongly recommended before starting to play with Magisk.
The Magisk version used for this tutorial is Magisk 25.1 and Magisk 25.2; the ROM used was OmniROM (Android 12 based).
The phone used was an ASUS Zenfone 8 but the instructions should work on other phones also.
Installation
Magisk consists out of two parts:
The Magisk App and the Magisk files in the boot partition. Without the files in the boot partition Magisk can do more or less nothing.
The Magisk App can be installed using the standard Android tools for installing apps.
The installation of the Magisk files into the boot partition can then be done using the Magisk App.
The official instructions to install Magisk into the boot partition are here:
https://topjohnwu.github.io/Magisk/install.html
Magisk can also be installed via script without user intervention into the boot partition -- see How to install Magisk into the boot partition using a script
Update 18.04.2023/bs
see How to install Magisk v26.0 or newer via script for how to install Magisk v26 via script
Note that the Magisk files for the boot partition must be reinstalled after an OS upgrade but this can be done from within the Magisk App.
Uninstalling Magisk
Use the Button "Uninstall Magisk" in the Magisk App to uninstall Magisk.
The Magisk App can also remove the Magisk files from the boot partition.
To uninstall the Magisk App only via script do
Bash:
adb shell pm uninstall com.topjohnwu.magisk
To remove Magisk from the boot partition manually I suggest to flash the image of the original boot partition.
Installing Magisk Modules
Magisk Modules are extensions for Magisk to for example replace or add files to /system (and much more ... I suggest to study the documentation for Magisk for those that are interested in using Magisk)
Magisk Modules are distributed via ZIP files.
As of Magisk v25 or newer the official method to install Magisk Modules is to manually copy the ZIP file with the Magisk Module to the phone and then use the button "Install from storage" in the "Modules" sub menu in the Magisk App.
In previous versions of Magisk a Module browser to list and install Magisk Modules was part of the Magisk App but unfortunately the developer dropped that feature. Therefor you must search and download the available Magisk Modules using a browser on the phone or a PC.
Repositories with Magisk Modules are for example:
https://github.com/Magisk-Modules-Repo/
and
https://github.com/Magisk-Modules-Alt-Repo
A XDA thread about Magisk Modules (including a list of Magisk Modules) is here:
https://forum.xda-developers.com/t/collection-of-magisk-modules-v2.3575758/
There is now a new App for Android called "Fox's Magisk Module Manager" that can be used to list and download Magisk Modules to the phone (see https://github.com/Fox2Code/FoxMagiskModuleManager).
It's also possible to install a Magisk Module via script. The commands to install an Magisk Module via script are:
Bash:
# copy the Magisk Module to the phone
adb push /data/backup/Android/MagiskModules/Nano_for_Android_NDK-6_3-6300.zip /sdcard/Download/
# install the Module
#
# Note:
#
# The command can also be executed in a script runnning on the phone (without "adb shell")
#
adb shell magisk --install-module /sdcard/Download/Nano_for_Android_NDK-6_3-6300.zip
# reboot the phone
adb reboot
Example:
Code:
[[email protected] ~]$ adb push /data/backup/Android/MagiskModules/Nano_for_Android_NDK-6_3-6300.zip /sdcard/Download/
/data/backup/Android/MagiskModules/Nano_for_Android_NDK-6_3-6300.zip: 1 file pushed, 0 skipped. 37.6 MB/s (380554 bytes in 0.010s)
[[email protected] ~]$ adb shell magisk --install-module /sdcard/Download/Nano_for_Android_NDK-6_3-6300.zip
- Current boot slot: _a
- Device is system-as-root
*****************************
Nano for Android NDK
by osm0sis @ xda-developers
*****************************
*******************
Powered by Magisk
*******************
Archive: /storage/emulated/0/Download/Nano_for_Android_NDK-6_3-6300.zip
inflating: diffusion_config.sh
inflating: module.prop
Mounting...
Extracting files...
Archive: /storage/emulated/0/Download/Nano_for_Android_NDK-6_3-6300.zip
inflating: META-INF/com/google/android/updater-script
inflating: META-INF/com/google/android/update-binary
inflating: sbin/nano
...
inflating: etc/terminfo/l/linux
inflating: customize.sh
inflating: update.json
inflating: bin/nano
inflating: bin/nano.bin
inflating: README.md
inflating: diffusion_config.sh
inflating: module.prop
Installing...
Installing nano to /data/adb/modules_update/nano-ndk/system/bin ...
Installing terminfo to /data/adb/modules_update/nano-ndk/system/etc ...
Unmounting...
Done!
[[email protected] ~]$ adb reboot
[[email protected] ~]$
Uninstalling a Magisk Module
Magisk Modules should be uninstalled via Magisk App if possible because there is no parameter for the magisk binary to uninstall a Magisk Module.
To force Magisk via shell command to remove the module after the next reboot create the file
remove
in the module directory.
If uninstalling the Magisk Module via Magisk does not work or if you want to uninstall a Magisk Module via script you can just delete the directory for the Magisk Module in /data/adb/modules and reboot the phone. This can be done in an adb shell or if that does not work anymore after rebooting the phone from a Recovery Image like TWRP, e.g.
Bash:
# uninstall the module "dummy_module" via adb shell commands
#
# check for an uninstall script for this module
#
if [ -x /data/adb/modules/dummy_module/uninstall.sh ] ; then
echo "Executing the module uninstall script ...."
/data/adb/modules/dummy_module/uninstall.sh
fi
adb shell rm -rf /data/adb/modules/dummy_module/
adb reboot
Note:
You should reboot the phone immediately after removing the directory with the Module.
This method is not really recommended.
List all installed Magisk Modules
The Magisk App will list all installed Magisk Modules
To list the installed Magisk Modules via CLI command use either
Bash:
adb shell ls -d /data/adb/modules/* | cut -f5 -d "/"
e.g.
Code:
[[email protected] ~]$ adb shell ls -d /data/adb/modules/* | cut -f5 -d "/"
PlayStore_for_MicroG
ccbins
dummy_module
initshell
nano-ndk
terminalmods
[[email protected] ~]$
# or
[[email protected] /]$ for i in $( adb shell su - -c ls -d /data/adb/modules/* ); do printf "%-30s %s\n" "${i##*/}" "$( adb shell su - -c grep name= $i/module.prop 2>/dev/null | cut -f2 -d "=" | tr -s " " )" ; done
MiXplorer MiXplorer
PlayStore_for_MicroG Patched Playstore from NanoDroid for MicroG (for ARM64 CPUs only)
ccbins Cross Compiled Binaries
dummy_module Dummy Module for testing a new module
initshell Create writable config files (/etc/profile) for sh
nano-ndk Nano for Android NDK
terminalmods Terminal Modifications
[[email protected] /]$
or on the phone:
Code:
[email protected]_I006D:/ # echo; for i in /data/adb/modules/*; do printf "%-30s %s\n" "${i##*/}" "$( grep name= $i/module.prop 2>/dev/null | cut -f2 -d "=" | tr -s " " )" ; done
PlayStore_for_MicroG Patched Playstore from NanoDroid for MicroG (for ARM64 CPUs only)
ccbins Cross Compiled Binaries
dummy_module
initshell Create writable config files (/etc/profile) for sh
nano-ndk Nano for Android NDK
terminalmods Terminal Modifications
[email protected]_I006D:/ #
How to disable a Magisk Module
To disable a Magisk Module via script create a file called disable in the Module directory, e.g.:
Bash:
touch /data/adb/modules/dummy_module/disable
The Magisk Module will then be disabled after the next reboot.
To re-enable the Magisk Module just delete the file disable in the Module directory and reboot the phone.
To list all disabled Magisk Modules do
Bash:
adb shell ls /data/adb/modules/*/disable | cut -f5 -d "/"
Replacing files in /system using a Dummy Magisk Module
One feature of Magisk Modules is the possibility to change files in the sub directories in the directory /system or also add new files to the sub directories in the directory /system. /system is mounted read-only and in the current Android version it is not possible to remount /system read-write anymore so without Magisk it's very difficult to change files in /system.
Please note that you can not create new files or directories in the directory /system using this Magisk feature.
To test this feature you do not need to create a Magisk Module : It's sufficient to simulate a Magisk Module.
For that just create the necessary directory structure and files manually.
Magisk Modules are are installed in the directory /data/adb/modules. Each Magisk Module use an uniqe sub directory in that directory. To simulate a Magisk Module open an adb shell as user root and create the directories for your Dummy Magisk Module, e.g.:
Bash:
mkdir /data/adb/modules/dummy_module
# Next create the sub directory system in that new directory
mkdir /data/adb/modules/dummy_module/system
Now copy the files for /system to that directory: The files in that directory will overwrite existing files in /system after the next reboot. Files in that directory that not already exist in /system will be created in /system.
e.g.
Code:
# contents of my Dummy Magisk Module
#
[email protected]_I006D:/data/adb/modules/dummy_module/system # pwd
/data/adb/modules/dummy_module/system
[email protected]_I006D:/data/adb/modules/dummy_module/system # find .
.
./bin
./bin/my_new_binary
./etc
./etc/my_new_file_for_systme
[email protected]_I006D:/data/adb/modules/dummy_module/system #
After rebooting the phone the files are visible in /system:
Code:
[email protected]_I006D:/ # ls -l /system/etc/my_new_file_for_systme
-rw-rw-rw- 1 root root 20 2022-07-20 16:55 /system/etc/my_new_file_for_systme
[email protected]_I006D:/ # cat /system/etc/my_new_file_for_systme
This is my new file
[email protected]_I006D:/ #
[email protected]_I006D:/ # ls -l /system/bin/my_new_binary
-rwxr-xr-x 1 root root 41 2022-07-20 16:57 /system/bin/my_new_binary
[email protected]_I006D:/ # my_new_binary
Hello world from my dummy binary
[email protected]_I006D:/ #
The permissions for the new files in /system are equal to the permissions of the original files in
/data/adb/modules/dummy_module so if the original files are writable you can also edit the new files in /system, e.g
Code:
[email protected]_I006D:/ # cat /system/etc/my_new_file_for_systme
This is my new file
[email protected]_I006D:/ #
[email protected]_I006D:/ # echo "Test Test" >> /system/etc/my_new_file_for_systme
[email protected]_I006D:/ # cat /system/etc/my_new_file_for_systme
This is my new file
Test Test
[email protected]_I006D:/ #
These changes are persistent (because they change the original file in /data/adb/modules/<modulename>). You can also edit the files in /data/adb/modules/<modulename> but be aware that you can not use tools that create temporary files for changing the files like for example sed: Changes done with these kind of tools are only visible after a reboot of the phone.
To change the file via script I recommend to create a new file and then replace the existing file with the new file using cp.
This Magisk feature can also be used to make files in sub directories in /system writable -- see How to make files in system writable for detailed instructions.
Make sure that the new files for /system are readable for the user using them; e.g some files (like for example apk files) are used by the user system). IMHO it's recommended to add the read permission (chmod o+r) to all new files for /system.
Notes:
Magisk does not really change the files in /system - instead it uses "bind mounts" to replace the files with others. Therefor you can always restore the original files by deleting the files in /data/adb/modules/<module_name> and rebooting the phone. Another big advantage of this technique is that you do not have to take care about an update of the OS:
changes done via Magisk will also work after an OS upgrade (assuming you reinstalled Magisk to the boot partition after installing the OS update)
Please be careful when changing existing files in /system.
To add the necessary infos for the Magisk App to list your dummy module properly just create the file module.prop for your Dummy Magisk Module, e.g.
Code:
[email protected]_I006D:/ # cat /data/adb/modules/dummy_module/module.prop
id=dummy-module
name=Dummy Module for testing a new module
version=1.0
versionCode=1000
[email protected]
description=Dummy Module ..
[email protected]_I006D:/ #
For some examples for this technique see
How to change files in the directory /system with Magisk
How to replace the Fake Store from OmniROM with MicroG with a patched Playstore
How to change the home directory for the user root on an Android phone
How to use this technique to disable an app that can not be uninstalled
Apps that can not be uninstalled can be disabled by creating empty files for the app.
Example:
My Magisk Module for the patched Playstore must disable the FakeStore installed in the OmniROM with MicroG by default.
That's done by creating an empty file in the Magisk Module for the apk file for the FakeStore, the result looks like this:
Code:
[email protected]_I006D:/ # ls -l /data/adb/modules/PlayStore_for_MicroG/system/priv-app/FakeStore/FakeStore.apk
-rw-r--r-- 1 root root 1 2022-07-15 11:54 /data/adb/modules/PlayStore_for_MicroG/system/priv-app/FakeStore/FakeStore.apk
[email protected]_I006D:/ #
[email protected]_I006D:/ # ls -l /system/priv-app/FakeStore/FakeStore.apk
-rw-r--r-- 1 root root 1 2022-07-15 11:54 /system/priv-app/FakeStore/FakeStore.apk
[email protected]_I006D:/ #
In case there are multiple files in the folder for the app you can also hide the entire folder:
From the original documentation from https://topjohnwu.github.io/Magisk/guides.html:
If you place a file named .replace in any of the folders, instead of merging its contents, that folder will directly replace the one in the real system. This can be very handy for swapping out an entire folder.
Click to expand...
Click to collapse
How to access the files replaced by Magisk
Use another bind mount to access the files replaced by Magisk, e.g:
Code:
[email protected]_I006D:/ # head /data/adb/modules/fmradio/system/etc/public.libraries.txt
# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
#
# 04.08.2022 /bs
# added the library libqcomfm_jni.so
#
libandroid.so
libaaudio.so
libamidi.so
libbinder_ndk.so
libc.so
[email protected]_I006D:/ #
[email protected]_I006D:/ #
[email protected]_I006D:/ # head /system/etc/public.libraries.txt
# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
#
# 04.08.2022 /bs
# added the library libqcomfm_jni.so
#
libandroid.so
libaaudio.so
libamidi.so
libbinder_ndk.so
libc.so
[email protected]_I006D:/ #
# -> The file /system/etc/public.libraries.txt is replaced by a file from a Magisk Module
# To access the original version of the file /system/etc/public.libraries.txt do
[email protected]_I006D:/ #
[email protected]_I006D:/ # mkdir -p /data/test
[email protected]_I006D:/ #
[email protected]_I006D:/ # mount -o bind /system /data/test
#
# -> /data/test is now bind mounted to /system
#
# -> /data/test/etc/public.libraries.txt is the original version of that file:
#
[email protected]_I006D:/ #
[email protected]_I006D:/ # head /data/test/etc/public.libraries.txt
# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
libandroid.so
libaaudio.so
libamidi.so
libbinder_ndk.so
libc.so
libcamera2ndk.so
libdl.so
libEGL.so
libGLESv1_CM.so
[email protected]_I006D:/ #
Replacing files in /vendor, /product, or /system_ext using a Dummy Magisk Module
The dummy Magisk Module can also be used to replace files in the directories /vendor, /product, or /system_ext:
from the Magisk documentation at https://topjohnwu.github.io/Magisk/guides.html:
If you want to replace files in /vendor, /product, or /system_ext, please place them under system/vendor, system/product, and system/system_ext respectively. Magisk will transparently handle whether these partitions are in a separate partition or not.
Click to expand...
Click to collapse
Note that this works only to replace existing files in these directories - you can not add new files to these directories using this method.
Example:
Code:
[email protected]_I006D:/ # cd /data/adb/modules/dummy_module/system
#
# files in the Magisk Module
#
[email protected]_I006D:/data/adb/modules/dummy_module/system # find . -type f
./bin/my_new_binary
./etc/my_new_file_for_systme
./product/mynewfile
./product/media/audio/alarms/Krypton.ogg
./vendor/mynewfile
./vendor/etc/sap.conf
./system_ext/mynewfile
./system_ext/etc/dpm/dpm.conf
[email protected]_I006D:/data/adb/modules/dummy_module/system #
#
# the new files for /product, /vendor, and /system_ext in the Magisk Module do not exist:
#
[email protected]_I006D:/data/adb/modules/dummy_module/system # ls -l /product/mynewfile /vendor/mynewfile /system_ext/mynewfile
ls: /product/mynewfile: No such file or directory
ls: /vendor/mynewfile: No such file or directory
ls: /system_ext/mynewfile: No such file or directory
#
# The existing files in /product, /vendor, and /system_ext are replaced with the files from the Magisk Moduel
#
[email protected]_I006D:/data/adb/modules/dummy_module/system # cksum ./product/media/audio/alarms/Krypton.ogg /product/media/audio/alarms/Krypton.ogg
4294967295 0 ./product/media/audio/alarms/Krypton.ogg
4294967295 0 /product/media/audio/alarms/Krypton.ogg
[email protected]_I006D:/data/adb/modules/dummy_module/system #
[email protected]_I006D:/data/adb/modules/dummy_module/system # cksum ./vendor/etc/sap.conf /vendor/etc/sap.conf
1967598015 7121 ./vendor/etc/sap.conf
1967598015 7121 /vendor/etc/sap.conf
[email protected]_I006D:/data/adb/modules/dummy_module/system #
[email protected]_I006D:/data/adb/modules/dummy_module/system # cksum ./system_ext/etc/dpm/dpm.conf /system_ext/etc/dpm/dpm.conf
1970692378 2925 ./system_ext/etc/dpm/dpm.conf
1970692378 2925 /system_ext/etc/dpm/dpm.conf
[email protected]_I006D:/data/adb/modules/dummy_module/system #
[email protected]_I006D:/data/adb/modules/dummy_module/system # grep mynewfile /cache/magisk.log
01-01 00:11:51.764 767 769 W : Unable to add: /product/mynewfile, skipped
01-01 00:11:51.771 767 769 W : Unable to add: /system_ext/mynewfile, skipped
01-01 00:11:51.771 767 769 W : Unable to add: /vendor/mynewfile, skipped
[email protected]_I006D:/data/adb/modules/dummy_module/system #
A work around to create new files in sub directories in /product, /vendor, or /system_ext:
Copy the complete existing folder to the sub directory in
/data/adb/modules/<magisk_module>/system/[product|vendor|system_ext]/
and create the file .replace in that directory and add the new file(s) to that directory.
Example:
Code:
[email protected]_I006D:/ # find /data/adb/modules/testmodule/
/data/adb/modules/testmodule/
/data/adb/modules/testmodule/system
/data/adb/modules/testmodule/system/product
/data/adb/modules/testmodule/system/product/lib
/data/adb/modules/testmodule/system/product/lib/.replace
/data/adb/modules/testmodule/system/product/lib/libframesequence.so
/data/adb/modules/testmodule/system/product/lib/libgiftranscode.so
/data/adb/modules/testmodule/system/product/lib/newfile001
/data/adb/modules/testmodule/system/vendor
/data/adb/modules/testmodule/system/vendor/app
/data/adb/modules/testmodule/system/vendor/app/TimeService
/data/adb/modules/testmodule/system/vendor/app/TimeService/TimeService.apk
/data/adb/modules/testmodule/system/vendor/app/TimeService/oat
/data/adb/modules/testmodule/system/vendor/app/TimeService/oat/arm64
/data/adb/modules/testmodule/system/vendor/app/TimeService/oat/arm64/TimeService.vdex
/data/adb/modules/testmodule/system/vendor/app/TimeService/oat/arm64/TimeService.odex
/data/adb/modules/testmodule/system/vendor/app/TimeService/newfile002
/data/adb/modules/testmodule/system/vendor/app/TimeService/.replace
/data/adb/modules/testmodule/system/system_ext
/data/adb/modules/testmodule/system/system_ext/app
/data/adb/modules/testmodule/system/system_ext/app/FM2
/data/adb/modules/testmodule/system/system_ext/app/FM2/.replace
/data/adb/modules/testmodule/system/system_ext/app/FM2/FM2.apk
/data/adb/modules/testmodule/system/system_ext/app/FM2/lib
/data/adb/modules/testmodule/system/system_ext/app/FM2/lib/arm64
/data/adb/modules/testmodule/system/system_ext/app/FM2/lib/arm64/libqcomfm_jni.so
/data/adb/modules/testmodule/system/system_ext/app/FM2/oat
/data/adb/modules/testmodule/system/system_ext/app/FM2/oat/arm64
/data/adb/modules/testmodule/system/system_ext/app/FM2/oat/arm64/FM2.odex
/data/adb/modules/testmodule/system/system_ext/app/FM2/oat/arm64/FM2.vdex
/data/adb/modules/testmodule/system/system_ext/app/FM2/newfile003
[email protected]_I006D:/ #
[email protected]_I006D:/ # find /data/adb/modules/testmodule/system | grep newfile
/data/adb/modules/testmodule/system/product/lib/newfile001
/data/adb/modules/testmodule/system/vendor/app/TimeService/newfile002
/data/adb/modules/testmodule/system/system_ext/app/FM2/newfile003
[email protected]_I006D:/ #
[email protected]_I006D:/ # pwd
/
[email protected]_I006D:/ # ls -l $( find /data/adb/modules/testmodule/system | grep newfile | cut -f6- -d "/" )
-rw-r--r-- 1 root root 0 2022-08-07 14:34 system/product/lib/newfile001
-rw-r--r-- 1 root root 0 2022-08-07 14:24 system/system_ext/app/FM2/newfile003
-rw-r--r-- 1 root root 0 2022-08-07 14:36 system/vendor/app/TimeService/newfile002
[email protected]_I006D:/ #
See How to change any file or directory using Magisk for another approach to change files on read-only mounted filesystems.
Executing scripts while booting the phone
Magisk also supports executing additional scripts while booting the phone.
The scripts to be executed must be copied to one of these directories
/data/adb/post-fs-data.d/
/data/adb/service.d/
see the description in the original Magisk documentation: https://topjohnwu.github.io/Magisk/details.html
Working examples for this technique are described in these posts:
How to run a script atevery boot using Magisk
How to disable or change the swap device in the Android 12 from ASUS for the Zenfone 8
How to create or change a swap device in the OmniROM 12 using Magisk
Another example for using this technique I found here
https://gist.github.com/niikoo/3f6bd13a69f2d68f3dd51cc667e79bdc :
Bash:
# Boot logging
# Create the file: /data/adb/post-fs-data.d/0001logcatboot
#!/system/bin/sh
mkdir -p /cache/logs
/system/bin/logcat -r 1024 -n 9 -v threadTime -f /cache/logs/log >info.log 2>err.log &
Note that I added commands to create / cleanup the log directory and changed the logcat command on my phone:
Bash:
#!/system/bin/sh
mkdir -p /cache/logs
rm -rf /cache/logs/*
/system/bin/logcat -r 102400 -n 9 -v threadTime -f /cache/logs/log >/cache/logs/info.log 2>/cache/logs/err.log &
To execute additional scripts earlier in the boot process you must add them to the boot image -- see the section Using Magisk to unpack and repack the boot image below for details.
Creating Magisk Modules
The official documentation for creating a Magisk Module is here: https://topjohnwu.github.io/Magisk/guides.html
Creating Magisk Modules that only use the standard features isn't that difficult and the official documentation should be sufficient.
I suggest to download an existing simple Magisk Module; unzip the ZIP file and study the contents.
Using Magisk to unpack and repack the boot image
The binary magiskboot that is part of the Magisk package can be used to unpack and repack the boot partition for every phone supported by Magisk.
For details see here: How to change files in the boot image using Magisk
Magisk also supports changing files in the root directory via Root Directory Overlays (see https://github.com/topjohnwu/Magisk/blob/master/docs/guides.md) :
This feature can be used to create additional start or stop services for the Android OS:
Android uses init *rc files to define the services to start when booting and also to define the services to run when doing the shutdown (like the systemd or initd in other Linux implementations).
These files are read early in the boot process and therefore reside only in the ramdisk on the boot partition. To add new init* rc files the boot image must be modified. This can be done with Magisk:
Just add the new init*rc files and optimal other scripts or files to the boot image using Magisk . Magisk will then take care of processing the new init*rc files by the Android operating system when booting the phone.
See these posts:
How to run a script at shutdown
How to trigger an action when a property is changed
How to enable root access using Magisk in a script
for examples for using that feature.
There are also magiskboot binaries for x86 in the Magisk apk file that can be used on a PC running the Linux OS:
see How to process Android boot image files on a PC running the Linux OS for more details about this feature.
Using Magisk to change the active slot
The Magisk App can also be used to change the active slot on phones with A/B slots -- for details see here :
How to manually switch the active slot
Directories and files used by Magisk
The directories and files used by Magisk are documented here https://topjohnwu.github.io/Magisk/guides.html
Some important directories and files for developing and trouble shooting Magisk Modules are:
The logfile used by Magisk is
/cache/magisk.log
In case something goes wrong with a Magisk Module you should first check that file.
The base directory for the data files for Magisk is
/data/adb
The config setttings for Magisk are stored in the SQLite database
/data/adb/magisk.db
To view (or probably) change the database entries via script you can either use sqlite3 binary (if installed)
Code:
ASUS_I006D:/ # sqlite3 /data/adb/magisk.db
SQLite version 3.7.6.3-Titanium
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .headers on
sqlite> .mode column
sqlite>
sqlite> .tables
denylist policies settings strings
sqlite>
sqlite> .schema
CREATE TABLE denylist (package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));
CREATE TABLE policies (uid INT, policy INT, until INT, logging INT, notification INT, PRIMARY KEY(uid));
CREATE TABLE settings (key TEXT, value INT, PRIMARY KEY(key));
CREATE TABLE strings (key TEXT, value TEXT, PRIMARY KEY(key));
sqlite>
sqlite> select * from denylist ;
sqlite>
sqlite> select * from policies ;
uid policy until logging notification
---------- ---------- ---------- ---------- ------------
2000 2 0 1 1
10134 1 0 1 1
sqlite>
sqlite> select * from settings ;
key value
---------- ----------
denylist 0
su_biometr 0
sqlite>
sqlite> select * from strings ;
sqlite>
or the magisk binary, e.g:
Code:
ASUS_I006D:/ # magisk --sqlite 'select * from policies'
logging=1|notification=1|policy=2|uid=2000|until=0
ASUS_I006D:/ #
ASUS_I006D:/ # magisk --sqlite 'select * from settings'
key=denylist|value=0
key=su_biometric|value=0
ASUS_I006D:/ #
There is a handy little script to list all apps with root access in the XDA thread https://forum.xda-developers.com/t/magisk-general-support-discussion.3432382/page-2681 .
How to create the Magisk database manually
To create the Magisk database manually (e.g. after installing Magisk manually via script) these commands can be used:
Bash:
# start the Magisk daemon if necessary
#
MAGISK_DAEMON_IS_RUNNING=true
/data/adb/magisk/magisk64 -v || /data/adb/magisk/magisk64 --daemon && MAGISK_DAEMON_IS_RUNNING=false
#
# force Magisk to create the Magisk database if it not yet exists
#
/data/adb/magisk/magisk64 --sqlite "PRAGMA user_version"
# stop the Magisk daemon again
#
[ ${MAGISK_DAEMON_IS_RUNNING} = false ] && /data/adb/magisk/magisk64 --stop
To create the Magisk database using sqlite3 use these commands:
SQL:
.open ${CUR_MAGISK_DATABASE_FILE}
CREATE TABLE IF NOT EXISTS policies (uid INT, policy INT, until INT, logging INT,notification INT, PRIMARY KEY(uid));
CREATE TABLE IF NOT EXISTS settings (key TEXT, value INT, PRIMARY KEY(key));
CREATE TABLE IF NOT EXISTS strings (key TEXT, value TEXT, PRIMARY KEY(key));
CREATE TABLE IF NOT EXISTS denylist (package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));
PRAGMA user_version=6;
.exit
Note:
The Magisk database will be upgraded to the latest version automatically by the Magisk daemon after the next restart
Magisk root access configuration details
Magisk uses the table policies in the sqlite database /data/adb/magisk.db to store the list of root enabled apps.
See this post https://forum.xda-developers.com/t/how-to-enable-root-access-using-magisk-in-a-script.4527035/ for details about this feature and how to enable root access via Magisk using a script.
Magisk App installation directory
Use
Bash:
pm list packages -f | grep magisk
to get the Magisk App installation directory.
Credits: https://forum.xda-developers.com/t/magisk-general-support-discussion.3432382/page-2689#post-87694851
The Magisk App Configuration files
The Magisk App stores the configuration (e.g. the app settings) in the default directory for App Settings, on my phone this is
/data/user_de/0/com.topjohnwu.magisk/shared_prefs
The file in that directory used to store the settings is
com.topjohnwu.magisk_preferences.xml
For more details about the file see the post Where does the Magisk App store the settings?.
Temporary Magisk config directory
While running Magisk uses a temporary directory for the configuration.
The path to the config directory can be retrieved via magisk binary:
Code:
ASUS_I006D:/dev/hP3B # magisk --path
/dev/hP3B
ASUS_I006D:/dev/hP3B#
The contents of that directory look like :
Code:
ASUS_I006D:/dev/hP3B # ls -al /dev/hP3B/
total 568
drwx------ 3 root root 200 1970-01-01 04:08 .
drwxr-xr-x 27 root root 5480 2022-11-06 18:32 ..
drwxr-xr-x 8 root root 180 1970-01-01 04:08 .magisk
lrwxrwxrwx 1 root root 10 1970-01-01 04:08 magisk -> ./magisk64
-rwxr-xr-x 1 root root 0 1970-01-01 04:08 magisk32
-rwxr-xr-x 1 root root 247168 1970-01-01 04:08 magisk64
-rwxr-xr-x 1 root root 328240 1970-01-01 04:08 magiskpolicy
lrwxrwxrwx 1 root root 8 1970-01-01 04:08 resetprop -> ./magisk
lrwxrwxrwx 1 root root 8 1970-01-01 04:08 su -> ./magisk
lrwxrwxrwx 1 root root 14 1970-01-01 04:08 supolicy -> ./magiskpolicy
ASUS_I006D:/dev/hP3B # ls -al /dev/hP3B/.magisk/
total 7
drwxr-xr-x 8 root root 180 1970-01-01 04:08 .
drwx------ 3 root root 200 1970-01-01 04:08 ..
d--------- 2 root root 160 1970-01-01 04:08 block
drwxr-xr-x 2 root root 7240 1970-01-01 04:08 busybox
---------- 1 root root 127 1970-01-01 04:08 config
d--------- 7 root root 220 1970-01-01 04:08 mirror
drwxr-xr-x 3 root root 3452 2022-11-06 18:32 modules
drwxr-xr-x 2 root root 0 1970-01-01 04:08 pts
d--------- 2 root root 80 1970-01-01 04:08 selinux
ASUS_I006D:/dev/hP3B # cat /dev/hP3B/.magisk/config
KEEPVERITY=false
KEEPFORCEENCRYPT=false
PATCHVBMETAFLAG=false
RECOVERYMODE=false
SHA1=1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/dev/hP3B #
Backup of the boot partitions
Magisk creates backups of the boot partitions in sub directories in /data/adb with filenames starting with magisk_backup_, e.g.:
Code:
[email protected]_I006D:/data/adb # ls -l /data/magisk_backup_*
/data/magisk_backup_79f3370cd83d03441325998a8875888780c3182f:
total 31712
-rwxr-xr-x 1 root root 32436260 2022-09-26 12:20 boot.img.gz
/data/magisk_backup_a0c712541fd002c331c25772a3b8609ae2fba546:
total 31712
-rwxr-xr-x 1 root root 32436965 2022-09-27 19:30 boot.img.gz
[email protected]_I006D:/data/adb #
The uniq string after the second underscore in the name of the directory with the backup is the SHA-1 from the boot image that was patched to install Magisk:
Code:
[[email protected] /data/develop/android/scripts_on_linux]$ ./install_magisk_via_twrp.sh
install_magisk_via_twrp.sh version - v2.0.0.1 - add Magisk to the boot partition of a phone running Android using TWRP
....
Creating the boot image file "/sdcard/Download/boot_b.1086412.img" from the partition "/dev/block/by-name/boot_b" ...
196608+0 records in
196608+0 records out
100663296 bytes (96 M) copied, 0.313082 s, 307 M/s
Checking the result ...
-rw-rw---- 1 root media_rw 100663296 2022-11-06 16:01 /sdcard/Download/boot_b.1086412.img
...
OK, patching the boot partition "/dev/block/by-name/boot_b" was successfull
....
[[email protected] /data/develop/android/scripts_on_linux]$
The image file patched by Magisk in this example is /sdcard/Download/boot_b.1086412.img.
The backup of the boot partition on the phone created by Magisk for this installation is:
Code:
ASUS_I006D:/ # ls -ld /data/magisk_backup*
drwxr-xr-x 2 root root 3452 2022-11-06 17:14 /data/magisk_backup_1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/ #
ASUS_I006D:/ # ls -l /data/magisk_backup_1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
total 50692
-rw-r--r-- 1 root root 51852324 2022-11-06 17:14 boot.img.gz
ASUS_I006D:/ #
1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb is the SHA-1 from the image file used for the installation of Magisk:
Code:
ASUS_I006D:/ # sha1sum /sdcard/Download/boot_b.1086412.img
1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb /sdcard/Download/boot_b.1086412.img
ASUS_I006D:/ #
or
Code:
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # /data/adb/magisk/magiskboot sha1 /sdcard/Download/boot_b.1086412.img
1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/data/adb/workdir/unpack/ramdisk #
The SHA1 from the previous boot image is stored in the file /dev/hP3B/.magisk/config used by Magisk while running, e.g.:
Code:
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # cat /dev/hP3B/.magisk/config
KEEPVERITY=false
KEEPFORCEENCRYPT=false
PATCHVBMETAFLAG=false
RECOVERYMODE=false
SHA1=1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/data/adb/workdir/unpack/ramdisk #
/dev/hP3B is a directory on the temporary ramdisk used by Magisk while it is running.
Use the command magisk --path to retrieve the path for the current ramdisk while Magisk is running, e.g.:
Code:
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # magisk --path
/dev/hP3B
ASUS_I006D:/data/adb/workdir/unpack/ramdisk #
The SHA1 from the previous boot image is also stored in the file .backup/.magisk in the ramdisk of a boot image, e.g:
Code:
# Note: unpack the boot image and the ramdisk from the boot image to get that file
#
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # cat .backup/.magisk
KEEPVERITY=false
KEEPFORCEENCRYPT=false
PATCHVBMETAFLAG=false
RECOVERYMODE=false
SHA1=1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/data/adb/workdir/unpack/ramdisk #
To do it all in once use:
Bash:
grep "^SHA1=" $( magisk --path )/.magisk/config | cut -f2 -d "="
e.g.:
Code:
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # grep "^SHA1=" $( magisk --path )/.magisk/config | cut -f2 -d "="
1a05ccb9844d3ad4f6d1873dfbf76ebf83a5bdeb
ASUS_I006D:/data/adb/workdir/unpack/ramdisk # #
Backup the Magisk config
To backup the Magisk config just copy the directories in /data/adb except the directory /data/adb/magisk (that directory is used for the binaries only)
Code:
adb shell tar --exclude data/adb/magisk/ -czf /sdcard/Download/magisk_config_$( date +%Y-%m-%d).$$.tar /data/adb/
To restore the backup unpack the tar file on the phone and reboot the phone.
To also create a backup the settings from the Magisk App create a backup of the directory with the Magisk App Settings (see above for details).
Start/Stop the Magisk App
To start the Magisk App via CLI command use
Bash:
am start -n com.topjohnwu.magisk/.ui.MainActivity
To stop the Magisk App via CLI command use:
Bash:
am force-stop com.topjohnwu.magisk
Start/Stop the Magisk Daemon
To stop the Magisk Daemon use
Bash:
magisk --stop
Be aware that stopping the magisk daemon will remove all bind mounts for files in /system. To re-enable these bind mounts a reboot is required.
To start the Magisk Daemon use
Bash:
/data/adb/magisk/magisk64 --daemon
To check if the Magisk Daemon is running use
Bash:
/data/adb/magisk/magisk64 -v
Example output:
Code:
# Magisk Daemon is running
ASUS_I006D:/ # /data/adb/magisk/magisk64 -v
25.2:MAGISK:R
ASUS_I006D:/ #
# Magisk Daemon is not running
|ASUS_I006D:/ # /data/adb/magisk/magisk64 -v
No daemon is currently running!
1|ASUS_I006D:/ #
Building Magisk
The Magisk source code is available at
https://github.com/topjohnwu/Magisk
There are also instructions how to create a local copy of the repository and compile Magisk on that page. I've successfully build Magisk using these instructions.
Miscellaneous
magiskboot can also be used compress or decompress files:
Code:
1|ASUS_I006D:/data/adb/magisk # ./magiskboot
MagiskBoot - Boot Image Modification Tool
Usage: ./magiskboot <action> [args...]
Supported actions:
...
compress[=format] <infile> [outfile]
Compress <infile> with [format] to [outfile].
<infile>/[outfile] can be '-' to be STDIN/STDOUT.
If [format] is not specified, then gzip will be used.
If [outfile] is not specified, then <infile> will be replaced
with another file suffixed with a matching file extension.
Supported formats: gzip zopfli xz lzma bzip2 lz4 lz4_legacy lz4_lg
decompress <infile> [outfile]
Detect format and decompress <infile> to [outfile].
<infile>/[outfile] can be '-' to be STDIN/STDOUT.
If [outfile] is not specified, then <infile> will be replaced
with another file removing its archive format file extension.
Supported formats: gzip zopfli xz lzma bzip2 lz4 lz4_legacy lz4_lg
1|ASUS_I006D:/data/adb/magisk #
magiskboot is also used in TWRP to unpack and repack the boot image for installing Magisk
Using the magisk binary while the phone is booted into TWRP
If the used TWRP can mount the volume for /data you can also use the binary magisk while in TWRP. The magisk binary is not in the path while booted into TWRP - therefor you must use the fully qualified filename:
This is
/data/adb/magisk/magisk64
for 64 Bit CPUs and
/data/adb/magisk/magisk32
for 32 Bit CPUs.
Some functions of Magisk are only usable if the Magisk daemon is running. To start the Magisk daemon the Magisk binary can also be used - example:
Code:
# read the policies table from the Magisk squlite database
#
ASUS_I006D:/ # /data/adb/magisk/magisk64 --sqlite "select * from policies ;"
No daemon is currently running!
#
# -> the Magisk daemon is not running -> start it
#
1|ASUS_I006D:/ # /data/adb/magisk/magisk64 --daemon
ASUS_I006D:/ #
ASUS_I006D:/ # /data/adb/magisk/magisk64 --sqlite "select * from policies ;"
logging=1|notification=1|policy=2|uid=2000|until=0
logging=1|notification=1|policy=2|uid=10135|until=0
logging=1|notification=1|policy=2|uid=10143|until=0
logging=1|notification=1|policy=2|uid=10055|until=0
logging=1|notification=1|policy=2|uid=10142|until=0
ASUS_I006D:/ #
Use
Bash:
/data/adb/magisk/magisk64 -V
to check if the Magisk daemon is running
Use
Bash:
/data/adb/magisk/magisk64 --stop
to stop the Magisk Daemon, e.g.:
Code:
ASUS_I006D:/ # /data/adb/magisk/magisk64 -V
25200
# -> The Magisk Daemon is running
ASUS_I006D:/ # /data/adb/magisk/magisk64 --stop
ASUS_I006D:/ #
ASUS_I006D:/ # /data/adb/magisk/magisk64 -V
No daemon is currently running!
1|ASUS_I006D:/ # 2D
Trouble Shooting
If something went wrong and booting the phone does not work anymore after installing a Magisk Module just remove the files in /data/adb/modules/<modulename> and reboot the phone :
Either connect via adb to the not booting phone (this should be possible in most cases even if the boot process does not finish), delete the files, and reboot the phone. Or reboot the phone from a Recovery image like TWRP, delete the files in /data/adb/modules/<modulename>, and reboot the phone.
The same procedure can be used if booting the phone does not work anymore after adding another init script - just delete the new script in /data/adb/post-fs-data.d or /data/adb/service.d and reboot the phone
An error like this
Code:
08-06 18:41:39.341 +0000 1356 1726 W ziparchive: Unable to open '/system/app/AsusFMRadio/AsusFMRadio.apk': Permission denied
08-06 18:41:39.341 +0000 1356 1726 E system_server: Failed to open APK '/system/app/AsusFMRadio/AsusFMRadio.apk': I/O error
08-06 18:41:39.354 +0000 1356 1356 W PackageManager: Failed to parse /system/app/AsusFMRadio: Failed to parse /system/app/AsusFMRadio/AsusFMRadio.apk
is most of the time caused by missing read permissions for the file.
Use
Bash:
chmod o+r /system/app/AsusFMRadio/AsusFMRadio.apk
to fix it.
To catch errors from a script executed by Magisk you might use this technique:
Bash:
# redirect STDERR of all commands in the script to a file
#
exec 2>/data/script_stderr.log
set -x
... rest of your script
To remove all installed Magisk Modules using the official method use:
Code:
magisk --remove-modules
to remove all modules (but not the new init scripts!) and reboot the phone
According to the FAQ Magisk will not start if the phone is booted into safe mode (see
https://topjohnwu.github.io/Magisk/faq.html)
Be aware that after rebooting the phone again in normal mode all Magisk Modules are disabled and must be enabled again using either the Magisk App or a CLI command:
To reenable all Magisk Modules via shell command do
Bash:
adb shell rm /data/adb/modules/*/disable
Spoiler: History
HIstory
07.08.2022 /bs
Added additional infos about the permissions for new files for /system.
Added additional commands to the script for catching the OS logs while booting the phone
Added infos about a workaround to add new files to /product, /vendor, or /system_ext
Added infos about how to access file replaced by a Magisk Module
20.09.2022 /bs
Added new links to posts about configuring swap devices via Magisk script
Added a link to the post about how to use Magisk to unpack and repack the boot image
28.09.2022 /bs
Added infos about the backups of the boot partitions created by Magisk
30.09.2022 /bs
Added a short info about using Magisk Overlays to change files in the root filesystem
Added the URL for the post with how to change the active slot using the Magisk App
02.10.2022 /bs
Added a short info about Root Directory Overlay system from Magisk
04.10.2022 /bs
Add an URL to another post to use the Root Directory Overlay system from Magsik
Fixed some spelling errors and also some errors in the code examples
Added more details about changing files in /system
26.10.2022/bs
Added the section Miscellaneous
28.10.2022/bs
Added the section Start/Stop the Magisk App
Added the section Start/Stop the Magisk Daemon
02.11.2022 /bs
added the infos about the x86 version of the magiskboot executables in the Magisk apk file
fixed some spelling and formatting errors
04.11.2022/bs
add the link to the Howto about making a file in /system writable
corrected some formatting errors
06.11.2022/bs
added more details about the boot partition backups created by Magisk
added missing "su - -c" to some adb shell commands
07.11.2022/bs
added more details about the boot partition backups created by Magisk
added the section about the temporary Magisk config directory
08.11.2022/bs
added the section about how to get the Magisk App installation directory
25.11.2022/bs
added infos about how to build Magisk using a local copy of the repository
02.12.2022 /bs
added the infos about sing the magisk binary while the phone is booted into TWRP
06.12.2022 /bs
added the section Magisk root access configuration details
added infos about the files used to store the settings for the Magisk App
30.12.2022 /bs
added more infos about how to add new start / stop services in Android
07.05.2023 /bs
add infos about how to create the Magisk database manuallay
Nice.
Thank you very much for all the details and explanations.
possible to change "Automatic Response" setting via adb command?
LEENO said:
possible to change "Automatic Response" setting via adb command?
Click to expand...
Click to collapse
What do you mean with "Automatic Response"?
bnsmb said:
What do you mean with "Automatic Response"?
Click to expand...
Click to collapse
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Most probably yes ... I will check that
LEENO said:
View attachment 5778489
Click to expand...
Click to collapse
Where does the Magisk App store the settings?
For installing and configuring an Android phone via script it is often required to boot the phone from an TWRP recovery image
Because of this I wrote a Linux shell script to reboot an Android phone from an TWRP recovery image:
boot_phone_from_twrp.sh
The script boot_phone_from_trwp.sh will detect the current status of the attached phone and use the approbiate commands (fastboot and/or adb) to reboot the phone from the TWRP recovery image.
The usage for the script is:
Code:
boot_phone_from_twrp.sh v2.2.0.0 - boot a phone from a TWRP image
boot_phone_from_twrp.sh [-h|help|-H] [serial=#sn|s=#sn] [wait=n] [force|noforce] [reboot|noreboot] [checkonly] [status] [twrp_image]
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Use the parameter -H to get a detailed usage help:
Spoiler: Detailed Usage
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ ./boot_phone_from_twrp.sh -H
boot_phone_from_twrp.sh v2.2.0.0 - boot a phone from a TWRP image
Usage
boot_phone_from_twrp.sh [-h|help|-H] [serial=#sn|s=#sn] [wait=n] [force|noforce] [reboot|noreboot] [checkonly] [status] [twrp_image]
All parameter are optional
Use the parameter "help" or "-H" to print the detailed usage help; use the parameter "-h" to print only the short usage help
Use the parameter "serial=#sn" to define the serialnumber of the phone to process. This parameter is only necessary if there
are more then one phones connected via USB and the environment variable SERIAL_NUMBER is not set.
The value for the parameter "wait" is the maximum number of seconds to wait after booting from the TWRP image until
the adb deamon is ready to use. The default value is 10 seconds.
Use the parameter "force" to reboot the phone from the TWRP image even if it's booted from a TWRP installed in
the boot or recovery partition.
Use the parameter "noforce" to disable rebooting the phone from the TWRP image if it's booted from a TWRP installed in
the boot or recovery partition. This is the default setting.
Use the parameter "reboot" to reboot the phone from the TWRP image even if it's already booted from an TWRP image.
Use the parameter "noreboot" to disable rebooting the phone from the TWRP image if it's already booted from an TWRP image
This is the default setting.
Use the parameter "checkonly" to only retrieve the current boot mode of the phone; the script will also return
the current status via return code; the possible values are 1 to 6 or one of the return codes indicating an error.
Use the parameter "status" to only print the current boot mode of the phone; the script will return
the current status via return code; the possible values are 1 to 6 or one of the return codes indicating an error.
The parameter "twrp_image" can be used to define another TWRP image to use. The parameter is optional - the
default for "twrp_image" is the value of the environment variable TWRP_IMAGE; the default for the variable
TWRP_IMAGE is hardcoded in the script in the variable DEFAULT_TWRP_IMAGE (= the TWRP image for the ASUS Zenfone 8)
Parameter overwrite the values defined via environment variables.
Returncodes:
0 - the phone was successfully booted from the TWRP image
1 - the phone is already booted from the TWRP image
2 - the phone is booted from TWRP installed in the boot or recovery partition
3 - the phone is booted into the Android OS
4 - the phone is booted into bootloader
5 - the phone is booted into the fastbootd
6 - the phone is booted into the safe mode of the Android OS
7 - the phone is booted into the LineageOS recovery installed in the boot or recovery partition
9 - too many phones connected
10 - usage help printed and exited
100 - invalid parameter found
101 - TWRP image not found
102 - booting the phone into the bootloader failed
103 - booting the phone into the TWRP failed
252 - access to the phone failed
253 - requirement check failed (e.g. one or more required executables not found, etc)
254 - unknown error
The phone to boot must be attached via USB.
The phone can be either in fastboot mode, in normal mode with enabled adb support, in the boot loader, or already booted from an installed TWRP or an TWRP image
To change some of the values used by the script you can set environment variables before starting the script:
Set the environment variable TWRP_IMAGE to the name of the TWRP image file that should be used (the parameter of the script will overwrite the variable)
Set the environment variable SERIAL_NUMBER to the serial number of the phone to patch if there is more then one phone connected via USB
Set the environment variable ADB_OPTIONS to the options to be used with the adb command
Set the environment variable FASTBOOT_OPTIONS to the options to be used with the fastboot command
Set the environment variable FAST_BOOT_WAIT_TIME to the maximum number of seconds to wait after booting the phone from the bootloader (default are 60 seconds)
Set the environment variable ADB_BOOT_WAIT_TIME to the maximum number of seconds to wait after booting the phone from the TWRP image (default are 60 seconds)
Set the environment variable ADB to the adb executable that should be used; default: search adb in the PATH
Set the environment variable FASTBOOT to the fastboot executable that should be used; default: search fastboot in the PATH
Set the environment variable TIMEOUT to the timeout executable that should be used; default: search timeout in the PATH
The default TWRP image to use is "/data/backup/ASUS_ZENFONE8/twrp/current_twrp.img"
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
When more than one phone is connected via USB use the parameter serial=#sn or the environment variable SERIAL_NUMBER to define the serial number of the phone to use.
To only retrieve the current status of the attached phone execute the script with the parameter checkonly or status.
The script will then only check the status of the phone and return the current status in the return code:
1 - the phone is booted from the TWRP image
2 - the phone is booted from TWRP installed in the boot or recovery partition
3 - the phone is booted into the Android OS
4 - the phone is booted into bootloader
5 - the phone is booted into the fastbootd
6 - the phone is booted into the safe mode of the Android OS
7 - the phone is booted into the LineageOS recovery installed in the boot or recovery partition
If the parameter status is used the script will also print a message with the current status of the phone,e.g:
Spoiler: example output
Code:
[[email protected] /data/develop/android/scripts_on_linux]$ ./boot_phone_from_twrp.sh checkonly ; echo "RC is $?"
boot_phone_from_twrp.sh v2.1.0.0 - boot a phone from a TWRP image
The script is running as user "xtrnaw7" -- will use "sudo" for the fastboot commands ...
Will use the attached phone with the serial number "M6AIB760D0939LX"
Using the default TWRP image: "/data/backup/ASUS_ZENFONE8/twrp/twrp-3.7.0_12-0-I006D.img"
Using the options " -s M6AIB760D0939LX " for the adb commands
Using the options " -s M6AIB760D0939LX " for the fastboot commands
Checking the script prerequisites ...
RC is 6
[[email protected] /data/develop/android/scripts_on_linux]$
[[email protected] /data/develop/android/scripts_on_linux]$ ./boot_phone_from_twrp.sh status ; echo "RC is $?"
boot_phone_from_twrp.sh v2.1.0.0 - boot a phone from a TWRP image
The script is running as user "xtrnaw7" -- will use "sudo" for the fastboot commands ...
Will use the attached phone with the serial number "M6AIB760D0939LX"
Using the default TWRP image: "/data/backup/ASUS_ZENFONE8/twrp/twrp-3.7.0_12-0-I006D.img"
Using the options " -s M6AIB760D0939LX " for the adb commands
Using the options " -s M6AIB760D0939LX " for the fastboot commands
Checking the script prerequisites ...
The phone is currently booted into the safe-mode of the Android OS
RC is 6
[[email protected] /data/develop/android/scripts_on_linux]$
The script boot_phone_from_twrp.sh can also be used as include file using
. ./boot_phone_from_twrp.sh
Using this method these functions are available in the script that includes boot_phone_from_twrp.sh:
retrieve_phone_status
print_phone_status
boot_phone_from_the_TWRP_image
reboot_phone
wait_for_phone_to_be_in_the_bootloader
wait_for_phone_with_a_working_adb_connection
wait_for_the_adb_daemon
Please check the comments at the start of the script for details about using the script in this way; the command
Code:
grep "#S#" boot_phone_from_twrp.sh | cut -c4-
prins the hints for using the script as include file
Spoiler: Details for using the script as include
Code:
[[email protected] /data/develop/android/scripts_on_linux]$ grep "#S#"
boot_phone_from_twrp.sh | cut -c4-
---------------------------------------------------------------------
To use the script as include file add the statement
. boot_phone_from_twrp.sh
to your file
If used as include file the script will
- define these constants if not already defined:
__TRUE
__FALSE
- define these functions if not already defined:
LogMsg
LogError
isNumber
wait_some_seconds
- define these functions (overwriting existing functions with the same name)
check_prereqs_for_boot_phone_from_twrp
init_global_vars_for_boot_phone_from_twrp
set_serial_number
retrieve_phone_status
print_phone_status
boot_phone_from_the_TWRP_image
reboot_phone
wait_for_phone_to_be_in_the_bootloader
wait_for_phone_with_a_working_adb_connection
wait_for_the_adb_daemon
- the variable PHONE_BOOT_ERROR contains the error code (102 or 103) if rebooting the phone fails
The script including this script can optional define these variables before
including this script (see the source code below for the meaning of these variables):
SUDO_PREFIX
CUR_USER
FORCE_BOOT_INTO_TWRP_IMAGE
FORCE_REBOOT_INTO_TWRP_IMAGE
TWRP_IMAGE
SERIAL_NUMBER
ADB_DAEMON_WAIT_TIME
FAST_BOOT_WAIT_TIME
ADB_BOOT_WAIT_TIME
FASTBOOT_OPTIONS
ADB_OPTIONS
ADB
FASTBOOT
TIMEOUT
CHECKONLY
The global variables listed above will be defined after including this script
[[email protected] /data/develop/android/scripts_on_linux]$
Note:
After including the script you should use the command
${ADB} ${ADB_OPTIONS}
to run the adb binary and the command
${FASTBOOT} ${FASTBOOT_OPTIONS}
to run the fastboot binary.
Examples:
To boot the phone from the TWRP image use this code:
Code:
. ./boot_phone_from_twrp.sh
retrieve_phone_status
boot_phone_from_the_TWRP_image
To boot the phone into the Android OS use this code:
Code:
. ./boot_phone_from_twrp.sh
retrieve_phone_status
reboot_phone
Spoiler: Simple test script
Code:
[[email protected] /data/develop/android/scripts_on_linux]$ cat ./test.sh
echo "*** Loading the functions to boot the phone ..."
. ./boot_phone_from_twrp.sh
echo ""
echo "*** Checking the status of the phone"
retrieve_phone_status
print_phone_status
echo ""
echo "*** Booting the phone into the TWRP image ..!"
boot_phone_from_the_TWRP_image
echo ""
echo "*** Press return to boot the phone into the Android OS ..."
read USER_INPUT
reboot_phone
[[email protected] /data/develop/android/scripts_on_linux]$
[[email protected] /data/develop/android/scripts_on_linux]$
[[email protected] /data/develop/android/scripts_on_linux]$ ./test.sh
*** Loading the functions to boot the phone ...
The script is running as user "xtrnaw7" -- will use "sudo" for the fastboot commands ...
Will use the attached phone with the serial number "M6AIB760D0939LX"
Using the default TWRP image: "/data/backup/ASUS_ZENFONE8/twrp/twrp-3.7.0_12-0-I006D.img"
Using the options " -s M6AIB760D0939LX " for the adb commands
Using the options " -s M6AIB760D0939LX " for the fastboot commands
Checking the script prerequisites ...
Will wait up to 60 second(s) after booting the phone into the bootloader
Will wait up to 60 second(s) after booting the phone from the TWRP image
Will wait up to 10 second(s) until the adb daemon is ready to use
*** Checking the status of the phone
The phone is currently booted from the Android OS
*** Booting the phone into the TWRP image ..!
The phone is booted into the Android OS
Booting the phone into the bootloader now ...
Waiting up to 60 seconds for the boot into the fastboot mode ...
The phone is booted into the bootloader
Booting the phone from the TWRP image "/data/backup/ASUS_ZENFONE8/twrp/twrp-3.7.0_12-0-I006D.img" now ...
Sending 'boot.img' (98304 KB) OKAY [ 2.761s]
Booting OKAY [ 10.361s]
Finished. Total time: 13.167s
Waiting up to 60 seconds for the boot of the phone ....
Waiting up to 10 seconds for the adb daemon to get ready ..
... the adb daemon is ready after second(s)
The phone is booted into TWRP: "twrp_I006D" version "3.7.0_12-0"
*** Press return to boot the phone into the Android OS ...
Booting the Android OS using the command "adb reboot " now ...
Waiting up to 60 seconds for the boot of the phone .....
Waiting up to 10 seconds for the adb daemon to get ready ..........
[[email protected] /data/develop/android/scripts_on_linux]$
The script boot_phone_from_twrp.sh is used as include script in the script init_magisk_db.sh - see this post How to enable root access using Magisk in a script. The script is also used in the script install_os_via_twrp.sh see this post How to install an OS image using the twrp command in a script .
The script boot_phone_from_twrp.sh is also available on my homepage:
http://bnsmb.de/files/public/Android/boot_phone_from_twrp.sh
Spoiler: Changelog for the script boot_phone_from_twrp.sh
Bash:
# History
# 05.11.2022 v1.0.0.0 /bs #VERSION
# inital release
#
# 01.12.2022 v2.0.0.0 /bs #VERSION
# script rewritten using functions
# added the parameter --serial=#sn
#
# 07.12.2022 v2.1.0.0 /bs #VERSION
# added a check for the Android OS safe mode
# missing shift command in the code to process the parameter for the serial number -- fixed
#
# 17.12.2022 v2.2.0.0 /bs #VERSION
# added support for the LineageOS recovery
Spoiler: History
17.12.2022 /bs
Updated the post with the infos for the script version 2.2.0.0
18.12.2022 /bs
Added some details for using the script as include file
Added a link to another script using this script
The most important step to automate the installation and configuration of the Android OS is the installation of an OS image via script without user intervention. One method to do that is using the binary twrp from the recovery TWRP .
The twrp command to install an OS image with twrp is
Code:
/system/bin/twrp install /path/to/update.zip
The usage for the binary twrp is (see also here)
Spoiler: twrp usage help
Code:
I006D:/ # /system/bin/twrp --help
TWRP openrecoveryscript command line tool, TWRP version 3.7.0_12-0
Allows command line usage of TWRP via openrecoveryscript commands.
Some common commands include:
install /path/to/update.zip
backup <SDCRBAEM> [backupname]
restore <SDCRBAEM> [backupname]
wipe <partition name>
format data
sideload
set <variable> [value]
decrypt <password> [USER ID]
remountrw
fixperms
mount <path>
unmount <path>
listmounts
print <value>
mkdir <directory>
reboot [recovery|poweroff|bootloader|download|edl]
See more documentation at https://twrp.me/faq/openrecoveryscript.html
I006D:/ #
The binary twrp can also be used to wipe the data from the phone using the parameter wipe <partition_name>.
The command twrp install will not change the active boot slot for the next reboot so this must be done manually after installing the OS image. This can be done using the binary bootctl which is also part of TWRP.
The usage for the command bootctl is:
Spoiler: bootctl usage help
Code:
ASUS_I006D:/ # /system/bin/bootctl -h
/system/bin/bootctl - command-line wrapper for the boot HAL.
Usage:
/system/bin/bootctl COMMAND
Commands:
hal-info - Show info about boot_control HAL used.
get-number-slots - Prints number of slots.
get-current-slot - Prints currently running SLOT.
mark-boot-successful - Mark current slot as GOOD.
get-active-boot-slot - Prints the SLOT to load on next boot.
set-active-boot-slot SLOT - On next boot, load and execute SLOT.
set-slot-as-unbootable SLOT - Mark SLOT as invalid.
is-slot-bootable SLOT - Returns 0 only if SLOT is bootable.
is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.
get-suffix SLOT - Prints suffix for SLOT.
set-snapshot-merge-status STAT - Sets whether a snapshot-merge of any dynamic
partition is in progress. Valid STAT values
are: none, unknown, snapshotted, merging,
or cancelled.
get-snapshot-merge-status - Prints the current snapshot-merge status.
SLOT parameter is the zero-based slot-number.
64|ASUS_I006D:/ #
Afterwards the phone can be rebooted to activate the new installed OS
So the commands for installing an OS image via twrp are
- boot the phone from the TWRP image
- (optional) use twrp to wipe the data
- copy the OS image file via adb push to the phone
- install the OS image file via the twrp binary
- change the next active boot slot via the binary bootctl.
- reboot the phone
I wrote a simple script to just do that
install_os_via_twrp.sh
The usage of the script is :
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ ./install_os_via_twrp.sh -h
install_os_via_twrp.sh version - v1.0.0.0 - install an OS image via the TWRP command twrp
install_os_via_twrp.sh [-h|help|-H] [--reboot|--noreboot] [force] [wipe|wipeall] [wipe_cache] [wipe_data] [wipe_dalvik] [format_data] [format_metadata] [factory_reset] [os_image_file]
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Use the parameter --help or -H to view the detailed usage help
Spoiler: Detailed usage help for install_os_via_twrp.sh
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ ./install_os_via_twrp.sh -H
install_os_via_twrp.sh version - v1.0.0.0 - install an OS image via the TWRP command twrp
Usage
install_os_via_twrp.sh [-h|help|-H] [--reboot|--noreboot] [force] [wipe|wipeall] [wipe_cache] [wipe_data] [wipe_dalvik] [format_data] [format_metadata] [factory_reset] [os_image_file]
All parameter are optional, except the parameter for the OS image to install "os_image_file".
The parameter can be used in any order.
Use the parameter "help" or "-H" to print the detailed usage help; use the parameter "-h" to print only the short usage help
If the parameter "--reboot" is used the script will reboot the phone after successfully installing the OS image; to disable the automatic reboot use the parameter "--noreboot".
Default is to ask the user for confirmation to reboot the phone.
Use the parameter "wipe" or "wipeall" to wipe /data, /cache, and Dalvik before installing the OS image.
Use one or more of the parameter "wipe_cache", "wipe_data", or "wipe_dalvik" to only wipe some of the partitions used.
Use the parameter "format_metadata" to format the meta data partition; this wipe is NOT included in "wipe_all"
Use the parameter "format_data" to format the data partition; this wipe is NOT included in "wipe_all"
Use the parameter "factory_reset" to do a factory reset before installing the OS image; a factory reset is done by formatting the data and the metadata partitions.
Use the parameter "force" to ignore errors while wiping or formatting the data; without this parameter the script will abort if one of the wipe or format commands fails
To change some of the values used by the script these environment variables can be set before starting the script:
Set the environment variable REBOOT to "yes" before starting the script to automatically reboot the phone after enabling the root access
Set the environment variable REBOOT to "no" before starting the script to disable the automatic reboot after enabling the root access
Set the environment variable UPLOAD_DIR_ON_THE_PHONE to set the upload directory for the OS image file on the phone (default dir is /tmp; /tmp is mounted on a ramdiks)
See also the source code of the script
boot_phone_from_twrp.sh
for environment variables supported by this script
Prerequisites
- the phone must be connected via USB
- there must be a working connection to the phone using fastboot or adb
- a working TWRP image for the phone must exist
The script boot_phone_from_twrp.sh is required by this script -- see the source code of the script
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Note:
The script needs the helper script boot_phone_from_twrp.sh.sh (see How to boot a phone from a twrp recovery image)
Spoiler: Sample output of the script installing a new version of the same OS
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ REBOOT=yes /data/develop/android/scripts_on_linux/install_os_via_twrp.sh /data/backup/ASUS_ZENFONE8/omnirom/omni-13/omni-13-202212180505-zenfone8-MICROG.zip
install_os_via_twrp.sh version - v1.0.0.0 - install an OS image via the TWRP command twrp
Using the TWRP helper script "/data/develop/android/scripts_on_linux/boot_phone_from_twrp.sh"
The OS image to install is: "/data/backup/ASUS_ZENFONE8/omnirom/omni-13/omni-13-202212180505-zenfone8-MICROG.zip"
Reading the helper script "boot_phone_from_twrp.sh" ...
The script is running as user "xtrnaw7" -- will use "sudo" for the fastboot commands ...
Will use the attached phone with the serial number "M6AIB760D0939LX"
Using the default TWRP image: "/data/backup/ASUS_ZENFONE8/twrp/current_twrp.img"
Using the options " -s M6AIB760D0939LX " for the adb commands
Using the options " -s M6AIB760D0939LX " for the fastboot commands
Checking the script prerequisites ...
Will wait up to 60 second(s) after booting the phone into the bootloader
Will wait up to 60 second(s) after booting the phone from the TWRP image
Will wait up to 10 second(s) until the adb daemon is ready to use
Retrieving the current status of the phone ...
The phone is currently booted into the Android OS
The phone is booted into the Android OS
Booting the phone into the bootloader now ...
Waiting up to 60 seconds for the boot into the fastboot mode ...
The phone is booted into the bootloader
Booting the phone from the TWRP image "/data/backup/ASUS_ZENFONE8/twrp/current_twrp.img" now ...
Sending 'boot.img' (98304 KB) OKAY [ 2.833s]
Booting OKAY [ 10.359s]
Finished. Total time: 13.243s
Waiting up to 60 seconds for the boot of the phone ....
Waiting up to 10 seconds for the adb daemon to get ready ..
... the adb daemon is ready after second(s)
The phone is booted into TWRP: "twrp_I006D" version "3.7.0_12-0"
Waiting up to 10 seconds for the adb daemon to get ready
... the adb daemon is ready after second(s)
Coyping the OS image file "/data/backup/ASUS_ZENFONE8/omnirom/omni-13/omni-13-202212180505-zenfone8-MICROG.zip" to "/tmp/omni-13-202212180505-zenfone8-MICROG.zip" on the phone ...
adb: error: failed to read copy response8-MICROG.zip
/data/backup/ASUS_ZENFONE8/omnirom/omni-13/omni-13-202212180505-zenfone8-MICROG.zip: 1 file pushed, 0 skipped. 201.8 MB/s (1261116637 bytes in 5.959s)
adb: error: failed to read copy response
adb: device 'M6AIB760D0939LX' not found
Copying the image failed -- we will do another try in 5 seconds ...
/data/backup/ASUS_ZENFONE8/omnirom/omni-13/omni-13-202212180505-zenfone8-MICROG.zip: 1 file pushed, 0 skipped. 32.5 MB/s (1261116637 bytes in 37.056s)
Installing the OS image "/tmp/omni-13-202212180505-zenfone8-MICROG.zip" into the slot "_b" ...
Installing zip file '/tmp/omni-13-202212180505-zenfone8-MICROG.zip'
Flashing A/B zip to inactive slot: B
Step 1/2Step 2/2Updating partition details...
...done
Devices on super may not mount until rebooting recovery.
To flash additional zips, please reboot recovery to switch to the updated slot.
Done processing script file
OS image file "/tmp/omni-13-202212180505-zenfone8-MICROG.zip" successfully installed.
Now changing the next active slot to _b ...
... successfully changed the active slot for the next reboot
Rebooting the phone now ...
Booting the Android OS using the command "adb reboot " now ...
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Spoiler: Sample output of the script installing another OS in the inactive slot
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ /data/develop/android/scripts_on_linux/install_os_via_twrp.sh factory_reset /data/backup/ASUS_ZENFONE8/Lineage-19_Android12/lineage-19.1-20221216-nightly-sake-signed.zip
install_os_via_twrp.sh version - v1.0.0.0 - install an OS image via the TWRP command twrp
Using the TWRP helper script "/data/develop/android/scripts_on_linux/boot_phone_from_twrp.sh"
The OS image to install is: "/data/backup/ASUS_ZENFONE8/Lineage-19_Android12/lineage-19.1-20221216-nightly-sake-signed.zip"
Reading the helper script "boot_phone_from_twrp.sh" ...
The script is running as user "xtrnaw7" -- will use "sudo" for the fastboot commands ...
Will use the attached phone with the serial number "M6AIB760D0939LX"
Using the default TWRP image: "/data/backup/ASUS_ZENFONE8/twrp/current_twrp.img"
Using the options " -s M6AIB760D0939LX " for the adb commands
Using the options " -s M6AIB760D0939LX " for the fastboot commands
Checking the script prerequisites ...
Will wait up to 60 second(s) after booting the phone into the bootloader
Will wait up to 60 second(s) after booting the phone from the TWRP image
Will wait up to 10 second(s) until the adb daemon is ready to use
Retrieving the current status of the phone ...
The phone is currently booted into the Android OS
The phone is booted into the Android OS
Booting the phone into the bootloader now ...
Waiting up to 60 seconds for the boot into the fastboot mode ...
The phone is booted into the bootloader
Booting the phone from the TWRP image "/data/backup/ASUS_ZENFONE8/twrp/current_twrp.img" now ...
Sending 'boot.img' (98304 KB) OKAY [ 2.840s]
Booting OKAY [ 10.406s]
Finished. Total time: 13.286s
Waiting up to 60 seconds for the boot of the phone ....
Waiting up to 10 seconds for the adb daemon to get ready ..
... the adb daemon is ready after second(s)
The phone is booted into TWRP: "twrp_I006D" version "3.7.0_12-0"
Waiting up to 10 seconds for the adb daemon to get ready
... the adb daemon is ready after second(s)
Wiping all data including media ...
Done.
You may need to reboot recovery to be able to use /data again.
TWRP will not recreate /data/media on an FBE device. Please reboot into your rom to create /data/media
Formatting Metadata using mke2fs...
Done.
Done processing script file
Wiping the metadata ...
++ /usr/bin/adb -s M6AIB760D0939LX shell umount /dev/block/by-name/metadata
umount: /dev/block/sda22: Invalid argument
++ /usr/bin/adb -s M6AIB760D0939LX shell mke2fs -F -t ext4 /dev/block/by-name/metadata
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 4096 4k blocks and 4096 inodes
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
Coyping the OS image file "/data/backup/ASUS_ZENFONE8/Lineage-19_Android12/lineage-19.1-20221216-nightly-sake-signed.zip" to "/tmp/lineage-19.1-20221216-nightly-sake-signed.zip" on the phone ...
adb: error: failed to read copy responsey-sake-signed.zip
/data/backup/ASUS_ZENFONE8/Lineage-19_Android12/lineage-19.1-20221216-nightly-sake-signed.zip: 1 file pushed, 0 skipped. 313.7 MB/s (1114300349 bytes in 3.387s)
adb: error: failed to read copy response
adb: device 'M6AIB760D0939LX' not found
Copying the image failed -- we will do another try in 5 seconds ...
/data/backup/ASUS_ZENFONE8/Lineage-19_Android12/lineage-19.1-20221216-nightly-sake-signed.zip: 1 file pushed, 0 skipped. 32.5 MB/s (1114300349 bytes in 32.719s)
Installing the OS image "/tmp/lineage-19.1-20221216-nightly-sake-signed.zip" into the slot "_a" ...
Installing zip file '/tmp/lineage-19.1-20221216-nightly-sake-signed.zip'
Flashing A/B zip to inactive slot: A
Step 1/2Step 2/2Updating partition details...
...done
Devices on super may not mount until rebooting recovery.
To flash additional zips, please reboot recovery to switch to the updated slot.
Done processing script file
OS image file "/tmp/lineage-19.1-20221216-nightly-sake-signed.zip" successfully installed.
Now changing the next active slot to _a ...
... successfully changed the active slot for the next reboot
*** Press return to reboot the phone now
Rebooting the phone now ...
Booting the Android OS using the command "adb reboot " now ...
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Testenvironment
I tested the script using this hardware and software:
Hardware:
ASUS Zenfone 8
TWRP
TWRP 3.7.0.12
OS Images installed via script
OmniROM 12
OmniROM 13
LineageOS 19
The script does not work for the images with the original Android from ASUS; the OS installation works but the phone does not boot from the new installation
The script install_os_via_twrp.sh is also available on my home page:
install_os_via_twrp.sh
Trouble Shooting
To update the installed OS to a new version in most cases neither a wipe nor a factory reset is necessary.
To install a different distribution on the phone in most cases a factory reset is required. (e.g installing LIneageOS if the current OS is OmniROM)
For automatic installation and configuration of a phone running the Android OS the access via adb is required. "Unfortunately" the access via adb is disabled in most Android distributions (in reality it is of course good that the access via adb is disabled in the default setting! See also the notes regarding the LineageOS at the end of this post))
There are (at least) two ways to enable access via adb:
Manually via the GUI of Android on the phone or via the Android command settings executed by the user root in a shell ,e.g.:
Bash:
settings put global development_settings_enabled 1
settings put global adb_enabled 1
The latter can also be done in a script in an adb shell -- but of course we need a working adb connection ....
One way around this problem is to use Magisk:
In principle this could be done using an init script for Magisk:
Magisk allows to run scripts while booting the phone (see How to run a script at every boot using Magisk); this feature could be used to enable adb via script.
Unfortunately, this method no longer works in the latest Android versions (Androd 12 and Android 13; Android 11 not tested):
Android now uses encryption for most of the files in the subdirectories in /data and to initiate the encryption keys for the files in these directories, the phone must boot once from the installed OS.
To use a Magisk init script to enable the access via adb, we need to create files in the directories /data/adb and /data/misc/adb. If you create these files while booting into TWRP recovery without a configured Android operating system, these files will be created unencrypted, making it impossible to boot the installed Android operating system:
If the Android operating system finds unencrpyted files in these directories at the first reboot, it boots into the installed recovery with the famous error message "Cannot load Android system. Your data may be corrupt" (see How to fix the error "Cannot load Android system. Your data may be corrupt" for details)
Fortunately, the Android operating system does not encrypt files in the directory /data/recovery (and therefore continues booting if there are already files in that directory) and the part of Magisk in the boot partition does not need the Magisk files /data/adb.
So to enable the access via adb using Magisk, we can create a script in the directory /data/recovery and a new Init .rc file for the Android operating system to execute that script while the Android OS is booting - for details about how to do that see How to trigger an action when a property is changed.
The working method to enable adb via Magisk is as follows:
- Boot the phone from a recovery (like TWRP)
- Install the new OS image but do not reboot the phone (see How to install an OS image using the TWRP binary twrp for how to install the OS via the cli commands from TWRP)
- Install Magisk into the boot partition of the phone and delete all files in /data/adb afterwards (see How to install Magisk into the boot partition using a script for how to install Magisk via script)
- copy a script to the directory /data/recovery on the phone that will enable access via adb using the Android command settings and copy the public ssl keys for the access via adb to the directory /data/misc/adb on the phone
- install a new init .rc file via Magisk which executes the script in the direcory /data/recovery to enable the access via adb - this script will be executed while doing the 1st reboot of the new installed Android OS.
(see How to trigger an action when a property is changed for how to add a new init .rc file using Magisk)
- reboot the phone
I wrote two scripts to enable adb using this method:
enable_adb_using_magisk.sh
The script enable_adb_using_magisk.sh must run in an adb session in TWRP after the new OS was installed and after Magisk has been installed into the boot partition but before the first reboot of the new installed operating system.
The script enable_adb_using_magisk.sh
- creates the script /data/recover/enable_adb_via_service.sh on the phone to enable adb and install the public ssl key for access via adb
- creates a new init *rc file using Magisk that will run the script /data/recover/enable_adb_via_service.sh on the phone while doing the 1st reboot (after the file encryption for the files /data is initalized by the Android OS)
To use the script enable_adb_using_magisk.sh manually after installing the new OS and Magisk do while the phone is booted into TWRP:
Bash:
#
# copy the script enable_adb_using_magisk.sh to the directory /tmp on the phone
#
adb push enable_adb_using_magisk.sh /tmp/enable_adb_using_magisk.sh
# copy the public ssl key for access via adb to the directory /tmp on the phone
#
adb push $HOME/.android/adbkey.pub /tmp/adbkey.pub
# execute the script /tmp/enable_adb_using_magisk.sh on the phone
#
adb shell sh /tmp/enable_adb_using_magisk.sh
# reboot the phone into the new installed OS
#
adb reboot
Notes:
The script enable_adb_using_magisk.sh installs the init *rc file into the boot partition from the slot for the next reboot: In this scenario this is the slot with the new installed OS.
To specify the boot partition to use add the boot partition as parameter, e.g.
Bash:
adb shell sh /tmp/enable_adb_using_magisk.sh _a
The init *rc service used is:
Spoiler: init *rc service to enable adb
Code:
#
# additional RC service to enable the access via adb after the 1st boot into the new installed Android OS
#
service bnsmb_enable_adb /system/bin/sh /data/recovery/enable_adb_via_service.sh
user root
group root
seclabel u:r:magisk:s0
disabled
oneshot
on zygote-start
setprop sys.bnsmb_enable_adb_done 0
start bnsmb_enable_adb
#
# Note: the following entries are for testing only!
#
on zygote-start
write /data/recovery/semfile Here_I_am
setprop sys.bnsmb.test.okay 0
The script enable_adb_using_magisk.sh creates the files adb_keys and adb_temp_keys.xml in the directory /data/misc/adb if the public ssl key /tmp/adbkey.pub exists on the phone.
Note that the file /data/misc/adb/db_temp_keys.xml is an Android Binary XML fIle (see How to change files in Android XML Binary format for details about Android Binary XML files)
To avoid the manual steps listed above I wrote another script:
enable_access_via_adb.sh
The script enable_access_via_adb.sh does all the steps listed above; the usage for enable_access_via_adb.sh is
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ ./enable_access_via_adb.sh -h
enable_access_via_adb.sh version - v1.0.0.0 - shell script to enable adb access via an init .rc file configured via Magisk
enable_access_via_adb.sh [-h|help|-H] [--reboot|--noreboot] [--nopubkey|--pubkey]
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
Spoiler: Detailed Usage
Code:
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $ ./enable_access_via_adb.sh -H
enable_access_via_adb.sh version - v1.0.0.0 - shell script to enable adb access via an init .rc file configured via Magisk
Usage
enable_access_via_adb.sh [-h|help|-H] [--reboot|--noreboot] [--nopubkey|--pubkey]
All parameter are optional. The parameter can be used in any order.
Use the parameter "help" or "-H" to print the detailed usage help; use the parameter "-h" to print only the short usage help
If the parameter "--reboot" is used the script will reboot the phone after installing Init .rc file; to disable the automatic reboot use the parameter "--noreboot".
Default is to ask the user for confirmation to reboot the phone.
Use the parameter "--nopubkey" to disable configuring the public key of the current user on the PC for the access via adb; use the parameter "--pubkey" to configure
the public key; default is to configure the public key.
The default public ssl key used is the key in the file "${HOME}/.android/adbkey.pub".
To change some of the values used by the script these environment variables can be set before starting the script:
Set the environment variable PUBLIC_KEY_ON_PC to the file with the public ssl key to use for the access via adb if another public key should be used
Set the environment variable REBOOT to "yes" before starting the script to automatically reboot the phone after enabling the root access
Set the environment variable REBOOT to "no" before starting the script to disable the automatic reboot after enabling the root access
See also the source code of the script
boot_phone_from_twrp.sh
for environment variables supported by this script
Prerequisites
- the phone must be connected via USB
- Magisk must be already installed in the boot partition of the phone
- the phone must be either booted into the fastbootd or bootloader with a working fastboot connection
or already booted into a recovery image with working adb connnection
The scripts boot_phone_from_twrp.sh and enable_adb_using_magisk.sh are required by this script -- see the source code of the script
[ OmniRom 13 Dev - [email protected] /data/develop/android/scripts_on_linux ] $
So installing a new OS and enabling access via adb in a script without user intervention can be done using these commands:
Bash:
#
# do a factory reset and install the OS image using the TRWP binary twrp
#
REBOOT=no ./install_os_via_twrp.sh factory_reset /data/backup/ASUS_ZENFONE8/omnirom_local/omni-13/omni-13-20221211-zenfone8-MICROG.zip
# install Magisk into the boot sector of the partition with the new OS and delete all files in /data/adb afterwards
#
# The parameter delete_adb_dir for the script "install_magisk_via_twrp.sh" is only available in version 2.2.0.0 or newer of the script.
#
REBOOT=no ./install_magisk_via_twrp.sh next copy_apk delete_adb_dir
# enable adb and copy the public keys for adb via new init *rc file using Magisk in the boot partition
#
REBOOT=no ./enable_access_via_adb.sh
# reboot the phone
#
adb reboot
# wait until the new OS is booted and adb is enabled
#
adb wait-for-device
# install the Magisk App
#
./install_apk.sh /data/backup/Android/EssentialApps/Magisk-v25.2.apk
# install the Magisk directories and binaries in /data/adb
#
REBOOT=no ./install_magisk_via_twrp.sh adb_only
# (optional) enable root access for the adb shell
#
REBOOT=yes ./init_magisk_db.sh
Notes:
The script enable_access_via_adb.sh needs the helper script boot_phone_from_twrp.sh.sh and the script enable_adb_using_magisk.sh .
The scripts can be downloaded from my homepage:
enable_access_via_adb.sh
enable_adb_using_magisk.sh
boot_phone_from_twrp.sh
The other scripts mentioned in ths post can also be downloaded from my home page:
install_os_via_twrp.sh (see How to install an OS image using the TWRP binary twrp for a descripton of this script)
install_magisk_via_twrp.sh (see How to install Magisk into the boot partition using a script for a description for this script)
install_apk.sh (see How to install packages (apk files) for Android via script for a description for this script)
init_magisk_db.sh (see How to enable root access using Magisk in a script for a description for this script)
Disabling the service to enable access via adb
To only run once, the script enable_adb_using_magisk.sh creates the file /data/recovery/adb_initialized exists on the phone. If that file already exists when enable_adb_using_magisk.sh starts, the script will do nothing and end immediately.
Therefor, it's not necessary to delete the new init *rc service.
It might even be useful to leave the service installed, since it can be used for other purposes later by modifying the script
However, if necessary, you can either delete the script used by the init *rc service enable_adb_using_magisk.sh or reinstall the original boot partition to get rid of the new service completely:
Bash:
#
# while the phone is booted into the Android OS with enabled root access or while the phone is booted into TWRP
#
# use the parameter "yes" for the script to run without requesting user input
#
adb shell su - -c /data/recovery/work/restore_boot_partition.sh
Directories and files used
Name
Type
Content
Comment
/tmp/adbkey.pubfilessl public key that should be configured/tmp is on a ramdisk so this file is lost after booting the phone/data/recovery/workDirectorytemporary files used for enabling adb/data/recovery/work/enable_adb_via_service.rcfileinit *rc file added to the boot partition via Magiks/data/recovery/work/boot_a.imgfileimage of the original boot partition/data/recovery/work/original_boot_partition.imgSymLinklink to the image with the original boot partition/data/recovery/work/restore_boot_partition.shfileScript to restore the boot partition using the image of the original boot partition/data/recovery/work/header
/data/recovery/work/kernel
/data/recovery/work/ramdisk.cpiofilescontents of the boot partition/data/recovery/adbkey.pubfilepublic ssl key to be configured for access via adb/data/recovery/adb_temp_keys.xml.humanfileXML file with the configuration for the access via adb
(will be converted to an XML file in Android binary XML format in /data/misc/adb)/data/recovery/enable_adb_via_service.shfilescript to enable the access via adb and installl the public ssl key for the access via adb
The script is configured in the init*rc file /data/recovery/work/enable_adb_via_service.rc/data/recovery/enable_adb_via_service.logfilelog file created by the script /data/recovery/enable_adb_via_service.sh/data/recovery/adb_initializedfilesemphor file for the script /data/recovery/enable_adb_via_service.sh - if this file exists the script will do nothing/data/recovery/semfilefiletest file created by the new init *rc service/data/recovery/log.gz
/data/recovery/last_log.gz
/data/recovery/recovery.fstab
/data/recovery/storage.fstabfileFiles created by TWRPonly for information
Enabling access via adb in the LineageOS (Update 11.01.2023)
In the LineageOS 19 for the ASUS Zenfone 8 access via adb is enabled in the default configuration.
Therefor these instructions are not necessary. The only configuration that must be done on a phone running the LineageOS is to copy the public ssl keys to /data/misc/adb to enable the access via adb.
Unfortunately the method used for this described in this post seems not to work in the LineageOS.
In addition, root access via adb can be enabled in the developer settings in the LineageOS. Until now I did not find out how to enable the plain root access from the LineageOS from within a script.
userdebug builds
In userdebug builds of Android the access via adb (without authentification) is enabled in the default.
Trouble Shooting
The script enable_adb_using_magisk.sh uses the log file /data/recovery/enable_adb_via_service.log if executed via init *rc service.
To check if the init *rc file was configured successfully check the properties
sys.bnsmb_enable_adb_done
sys.bnsmb.test.okay
in the running Android OS. Both properties should be defined with the value 0:
Code:
ASUS_I006D:/ # getprop sys.bnsmb_enable_adb_done
0
ASUS_I006D:/ #
ASUS_I006D:/ # getprop sys.bnsmb.test.okay
0
ASUS_I006D:/ #
In addition, if everything worked there should exist the file /data/recovery/semfile.
Code:
130|ASUS_I006D:/ # ls -l /data/recovery/semfile
-rw------- 1 root root 9 2022-12-29 11:44 /data/recovery/semfile
ASUS_I006D:/ #
Use the Android command start to check if the service exists and can be started, e.g.
Spoiler: start bnsmb_enable_adb
Code:
ASUS_I006D:/ # start bnsmb_enable_adb ; dmesg | tail -10
[ 3069.861365] [ 3069.861365] (CPU:2-pid:1:init) [12:35:31.711593934] init: Service 'exec 613 (/system/bin/flags_health_check UPDATABLE_CRASHING)' (pid 5734) exited with status 0 waiting took 0.024000 seconds
[ 3069.861402] [ 3069.861402] (CPU:2-pid:1:init) [12:35:31.711630236] init: Sending signal 9 to service 'exec 613 (/system/bin/flags_health_check UPDATABLE_CRASHING)' (pid 5734) process group...
[ 3069.861618] [ 3069.861618] (CPU:2-pid:1:init) [12:35:31.711846069] libprocessgroup: Successfully killed process cgroup uid 1000 pid 5734 in 0ms
[ 3071.202534] [ 3071.202486] (CPU:2-pid:5077:wk:0xffffffe40) [12:35:33.052716433] [BAT][CHG]asus_jeita_cc_worker set BATTMAN_OEM_WORK_EVENT : WORK_JEITA_CC
[ 3071.220807] [ 3071.220807] (CPU:0-pid:350:wk:0xffffffe40) [12:35:33.071038100] [BAT][CHG]handle_message set property:16 successfully
[ 3071.570753] [ 3071.570753] (CPU:2-pid:1:init) [12:35:33.420982631] init: starting service 'bnsmb_enable_adb'...
[ 3071.575971] [ 3071.575971] (CPU:3-pid:1:init) [12:35:33.426199819] init: Control message: Processed ctl.start for 'bnsmb_enable_adb' from pid: 5735 (start bnsmb_enable_adb)
[ 3071.614570] [ 3071.614570] (CPU:3-pid:1:init) [12:35:33.464799298] init: Service 'bnsmb_enable_adb' (pid 5736) exited with status 0 oneshot service took 0.040000 seconds in background
[ 3071.614609] [ 3071.614609] (CPU:3-pid:1:init) [12:35:33.464837267] init: Sending signal 9 to service 'bnsmb_enable_adb' (pid 5736) process group...
[ 3071.614788] [ 3071.614788] (CPU:3-pid:1:init) [12:35:33.465016277] libprocessgroup: Successfully killed process cgroup uid 0 pid 5736 in 0ms
ASUS_I006D:/ #
If something does not work execute the script manually in an adb session to check :
Spoiler: /data/recovery/enable_adb_via_service.sh
Code:
ASUS_I006D:/ # rm -f /data/recovery/adb_initialized
ASUS_I006D:/ #
ASUS_I006D:/ #
ASUS_I006D:/ # sh -x /data/recovery/enable_adb_via_service.sh
+ tty -s
+ '[' 0 -ne 0 ']'
+ PATH=/system/bin:/product/bin:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin
+ export PATH
+ '[' ! -r /data/recovery/adb_initialized ']'
+ echo 'Sleeping 30 seconds now ...'
Sleeping 30 seconds now ...
+ sleep 30
+ touch /data/recovery/adb_initialized
+ settings put global development_settings_enabled 1
+ settings put global adb_enabled 1
+ '[' ! -d /data/misc/adb ']'
+ '[' ! -r /data/misc/adb/adb_keys ']'
+ '[' -r /data/recovery/adbkey.pub ']'
+ >>/data/misc/adb/adb_keys
+ cat /data/recovery/adbkey.pub
+ '[' -r /data/recovery/adb_temp_keys.xml.human ']'
+ xml2abx /data/recovery/adb_temp_keys.xml.human /data/misc/adb/adb_temp_keys.xml
+ chmod 0600 /data/misc/adb/adb_temp_keys.xml
+ chown system:shell /data/misc/adb/adb_temp_keys.xml
+ chcon -v u:object_r:adb_keys_file:s0 /data/misc/adb/adb_temp_keys.xml
chcon '/data/misc/adb/adb_temp_keys.xml' to u:object_r:adb_keys_file:s0
ASUS_I006D:/ #
Thank you for your explanation, I leave my footprint, I need this sometimes.
After installing an operating system update on a phone with the Android operating system and A/B slots, Magisk can be installed in the boot partition of the inactive slot with the new operating system version using the "Install to inactive slot" installation option in the Magisk App.
Unfortunately this option is not available for TWRP.
Therefor I wrote a litlle script to install TWRP into the boot partition of the inactive slot with the new operating system version after an OS upgrade.
The method works on my ASUS Zenfone 8 and should in principle also work on other phones with the same architecture (Qualcomm CPU, A/B slots, and boot partitions with ram disks)
Looking at the source code for TWRP (https://github.com/TeamWin/android_bootable_recovery/blob/android-12.1/twrpRepacker.cpp) it can be seen that the installation of TWRP is in principle only the installation of a new ramdisk:
Spoiler: TWRP source code excerpt
C++:
bool twrpRepacker::Flash_Current_Twrp() {
if (!TWFunc::Path_Exists("/ramdisk-files.txt")) {
LOGERR("can not find ramdisk-files.txt");
return false;
}
PartitionManager.Unlock_Block_Partitions();
Repack_Options_struct Repack_Options;
Repack_Options.Disable_Verity = false;
Repack_Options.Disable_Force_Encrypt = false;
Repack_Options.Type = REPLACE_RAMDISK_UNPACKED;
Repack_Options.Backup_First = DataManager::GetIntValue("tw_repack_backup_first") != 0;
std::string verifyfiles = "cd / && sha256sum --status -c ramdisk-files.sha256sum";
if (TWFunc::Exec_Cmd(verifyfiles) != 0) {
gui_msg(Msg(msg::kError, "modified_ramdisk_error=ramdisk files have been modified, unable to create ramdisk to flash, fastboot boot twrp and try this option again or use the Install Recovery Ramdisk option."));
return false;
}
std::string command = "cd / && /system/bin/cpio -H newc -o < ramdisk-files.txt > /tmp/currentramdisk.cpio && /system/bin/gzip -f /tmp/currentramdisk.cpio";
if (TWFunc::Exec_Cmd(command) != 0) {
gui_msg(Msg(msg::kError, "create_ramdisk_error=failed to create ramdisk to flash."));
return false;
}
if (!Repack_Image_And_Flash("/tmp/currentramdisk.cpio.gz", Repack_Options))
return false;
else
return true;
}
Therefor to install TWRP via script after an OS version update two steps are neccessary:
Step one
First we must create the ramdisk with TWRP; this step must only be done once for each TWRP version.
Boot the phone from the TWRP image (NOT from a TWRP installed in the recovery!), e.g:
Bash:
adb rebboot bootloader
sudo fastboot boot /data/backup/ASUS_ZENFONE8/twrp/twrp-3.7.0_12-0-I006D-enhanced.img
Then open an adb session to the running TWRP on the phone and execute:
Bash:
# create the RAM disk
#
cd / && sha256sum --status -c ramdisk-files.sha256sum
if [ $? -eq 0 ] ; then
cd / && /system/bin/cpio -H newc -o < ramdisk-files.txt > /tmp/ramdisk_with_twrp.cpio && /system/bin/gzip -f /tmp/ramdisk_with_twrp.cpio
fi
# copy the RAM disk and magiskboot to a directory on the internal storage that supports the execution permission bit (not /sdcard/<something>)
#
mkdir -p /data/develop/twrp
cp /tmp/ramdisk_with_twrp.cpio.gz /data/develop/twrp/ramdisk_with_twrp.cpio
cp /bin/magiskboot /data/develop/twrp/
Notes:
It is recommended to store the files ramdisk_with_twrp.cpio and magiskboot also on the PC.
The executable magiskboot is only required if Magisk is not installed on the phone.
Now copy the script install_twrp_ramdisk.sh.sh to the phone; this script can be copied to any filesystem with write access on the phone.
That's it .
Step two
The next time an OS update should be done using these steps:
1. install the new OS version either manually or via OTA but do NOT reboot afterwards.
2. execute the script install_twrp_ramdisk.sh.sh to install TWRP into the boot partition for the inactive slot either in an shell on the phone or in an adb shell, e.g. (sh is only necessary if the script is on a filesystem that does not support the execution permission)
Bash:
sh /sdcard/Download/install_twrp_ramdisk.sh
Note that the script needs root access to read and write the boot partition
3. optional: Install Magisk into the new boot partition using the install option "Install to inactive slot" in the Magisk App
4. reboot the phone to activate the new OS version
Test Environment
ASUS Zenfone 8
OmniROM 13
Magisk v25.2
TWRP 3.7.0
Notes
Set the environment variable WORK_DIR before executing the script to use another directory with the image
Set the environment variable TWRP_RAMDISK_NAME before executing the script to use another filename for the ram disk image.
see How to add additional files to an TWRP image for how to add additional files to the TWRP image
see How to install TWRP via script for how to install TWRP with a script running on the PC
Usage for the script install_twrp_ramdisk.sh:
Spoiler: ./install_twrp_ramdisk.sh -H
Code:
./install_twrp_ramdisk.sh -H
Usage:
install_twrp_ramdisk.sh [-h|-H]
This script must run in a shell on the phone (or in an adb shell) after an OS update was installed (either manual or via OTA) but before rebooting the phone.
The script will then install TWRP into the inactive slot.
The script must be executed by the user "root"; if it's executed by a non-root user it will restart itself using "su - -c scriptname"
Supported environment variables
WORK_DIR
directory with the ram disk image and probably the executable magiskboot
TWRP_RAMDISK_NAME
name of the file with the ram disk image (without path)
Prerequisites
The script requires these files:
/data/develop/twrp/ramdisk_with_twrp.cpio
- the ram disk with TWRP
/data/develop/twrp/magiskboot or /data/adb/magisk/magiskboot
- the magiskboot executable
To create the ram disk with TWRP do:
Boot the phone from the TWRP image (NOT from a TWRP installed in the recovery!),
open an adb session to the running TWRP on the phone and execute:
cd / && sha256sum --status -c ramdisk-files.sha256sum
if [ $? -eq 0 ] ; then
cd / && /system/bin/cpio -H newc -o < ramdisk-files.txt > /tmp/ramdisk_with_twrp.cpio && /system/bin/gzip -f /tmp/ramdisk_with_twrp.cpio
fi
mkdir -p /data/develop/twrp
cp /tmp/ramdisk_with_twrp.cpio.gz /data/develop/twrp/ramdisk_with_twrp.cpio
cp /bin/magiskboot /data/develop/twrp/
Note:
It is recommended to store the files ramdisk_with_twrp.cpio and magiskboot also on the PC.
The file magiskboot is only required if Magisk is not installed on the phone.
The directory used for the files can be any directory on the phone on a filesystem supporting the execute permission bit.
But do not forget to change the directory used in the script below (variable WORK_DIR) also.
Update 04.06.2023:
see https://github.com/Magisk-Modules-Repo/twrp-keep for a Magisk module with a script to reinstall TWRP into the inactive boot partition after an OS Udate
Update 11.06.2023:
I successfully tested the Magisk Module twrp-keep on an ASUS Zenfone 8 with OmniROM 13, TRWP 3.7.0_12, and Magisk v26.2.
ToDo:
Create an App with GUI to execute the script