如何在启动时运行可执行文件并将其保持运行? -- root-access 领域 和 linux 领域 和 scripts 领域 和 services 领域 和 init.d 领域 android 相关 的问题

How to run an executable on boot and keep it running?


简体版||繁體版
3
vote

问题

中文

我有一个来自 ndk-build 程序的可执行构建。我想在rooted android设备上运行它。 Android将杀死我可执行的可能性是多少?

使用 adb shell ,我能够使用以下命令执行我的可执行文件:

  adb push executable /sdcard adb shell device:/ $ su device:/ # cd /system device:/system # mount -o rw,remount /system device:/system # mv /sdcard/executable . device:/system # ./executable   

我的要求是在设备启动时运行此可执行文件。

我已经尝试过以下:

  1. 写入 ./executable init.rc 中。
    • 在重启中 init.rc 重置为其原始内容。我想到了这个Magisk完成了这一点。
  2. 在/ ettc/init/bootstat.rc中编写命令
    • ./executable
    • service custom /system/executable
    • on boot ./system/dhandler/diag_revealer

以上都没有工作。

english

I have an executable build from a ndk-build program. I want to run it on a rooted Android device. How much is the possibility that Android will kill my executable?

Using adb shell, I am able to execute my executable using following commands:

adb push executable /sdcard adb shell device:/ $ su device:/ # cd /system device:/system # mount -o rw,remount /system device:/system # mv /sdcard/executable . device:/system # ./executable 

My requirement is to run this executable on device boot.

I have tried following:

  1. Write ./executable in init.rc.
    • On reboot init.rc reset to its original contents. I figured out that Magisk done this.
  2. Write commands in /system/etc/init/bootstat.rc
    • ./executable
    • service custom /system/executable
    • on boot ./system/dhandler/diag_revealer

None of the above thing is working.

              
 
 

回答列表

6
 
vote
vote
最佳答案
 

Android将杀死我的可执行文件的可能性是多少?

特权本机进程通常不会被android杀死,除非它们无法处理内部发生错误,例如某些系统资源不可用或拒绝因为selinux等而被拒绝拒绝。释放内存,Android只会杀死进程在其框架内,即在 zygote 下运行。要管理本机进程的资源,Android使用 cgroups

当它们接收来自内核或其他用户佩勤程序的信号时杀死进程(例如,使用 kill 命令) 1 , 2 )。内核是实际的操作系统,对我们来说不可见,但处理我们用设备所做的一切。开发人员可以编程他的代码,如果收到,或完全忽略它。除 sigkill 之外。哪些不能通过计划处理,没有内核的警告,没有安全地退出宽限期,立即终止。但是内核不会介意你的存在,除非他在硬件资源短缺或开始行为不端。这就是为什么编程很重要。

程序可以通过uid ( 4 )。但是, init 内核启动的用户空间中的第一个进程是亲爱的,内核永远不会将危险信号转发到 init 。如果出于某种原因发生这种情况,内核会得到恐慌并重新启动( 5 。

总结在上面的行中,可以避免以编程方式或使用一些脚本技巧< / a> @ alecxs 已提到。但是如果您想确保您的进程应重新启动,如果被杀死,则定义Android Abcdefghijklmnabcdefghijklmn5 服务。

在重新启动中 init.rc 重置为其原始内容。我想到了Magisk完成了这一点。

否,magisk没有这样做。 Android的 rootfs 是一个临时文件系统(不是一个持久的文件,而不是 /system /data )在每一个重新启动时清除。根目录的内容( abcdefghijklmn10 )都是从名为 abcdefghijklmn11 的另一个分区中提取,其中包含 cgroups2 cgroups3 (虽然事情已更改 systo root )。因此,您无法永久更改<代码> ABCDefghijklmnaBCDEFGHIJKLMN14 除非您提取,修改,重新包装和刷新<代码> ABCDEFGHIJKLMNABCDEFGHIJKLMN15 。

但要定义一个新的Init服务,修改 cgroups6 不是必需的。 Android解析所有 cgroups7 文件来自 cgroups8 目录位于 abcdefghijklmn19 kill0 ( 6 )。所以你可以创建自己的 kill1 文件。


注意: 为了获得真正的root权限并处理selinux,下面给出的所有选项都依赖于Magisk。查看此答案详细信息。

init.d脚本

您可以使用传统 kill2 - magisk的功能,以启动启动过程。 创建脚本 kill3

  kill4 / code> 

* kill5 是shell的伪信号。
* android的 kill6 (来自 kill7 )是buggy,更好地使用 kill8 applet。

将可执行文件放在 kill9 并设置权限:

  init0  

您还可以在 init1 中放置脚本,但这是一点初步执行。确保在该阶段可用文件系统路径(以及其他需要的资源)。

从init

执行程序

另一种方法是直接从init执行二进制。创建 init2 文件:

  init3  

设置权限:

  init4  

,这就是全部!重新启动设备以进行更改以生效。

但是它是一次执行一次,不会重新启动。此外, init5 文件中还有一些shell脚本功能。例如,您无法将stdout / stderr重定向到文件,这必须由可执行程序本身处理。所以我们可以尝试利用两者; shell脚本和 init6 文件:

init服务

而不是直接从 init7 文件中执行二进制文件,而不是执行shell脚本。创建脚本 init8

  init9  

create init0 服务:

  init1  

设置 init2 init3 init4 ,如上所述并重新启动。

其他参数 7 ) init5 init6 init7,如果要将该服务运行为非特权,则是必需的用户。授予 最不需要的权限 是安全的角度的推荐方法。请参阅此答案有关功能和selinux的更多详细信息。

init8 如果被杀死,每5秒(默认情况下)将继续重新启动服务。您可以使用 init9 停止服务。替换 init0 使用 init1 重新开始。
要查看服务会发生什么: init2

相关

  • 如何使用superuser selinux上下文运行Android Init服务?
  • 如何在adb shell中运行脚本?

 

How much is the possibility that Android will kill my executable?

Privileged native processes usually don't get killed by Android except if they can't handle an error occurred inside, such as some system resource not available or permission denied because of SELinux etc. To free up memory, Android only kills processes within its framework i.e. running under zygote. To manage resources for native processes, Android uses cgroups.

Processes are killed when they receive SIGNALS from kernel or other userspace programs (e.g. with kill command) (1, 2). Kernel is the actual operating system, not visible to us but handling everything we do with device. A developer can program his code how to react to a specific signal if received, or completely ignore it (3). Except SIGKILL. Which can't be handled by program, no warning from kernel, no grace period to exit safely, just being terminated immediately. But kernel won't mind your presence unless he gets short on hardware resources or you start misbehaving. That's why programming is important.

Programs can send each other signals (including KILL), which are forwarded by kernel, governed by UID (4). However, init the very first process in userspace started by kernel is the dear one, kernel never forwards dangerous signals to init. And if this happens for some reason, kernel gets panic and reboots (5).

Summarizing above lines, it is possible to avoid being killed (AMAP) programmatically or using some scripting tricks as @alecxs has mentioned. But if you want to make sure that your process should restart if gets killed, define an Android init service.

On reboot init.rc reset to its original contents. I figured out that Magisk done this.

No, Magisk didn't do this. Android's rootfs is a temporary filesystem (not a persistent one like on /system or /data) that gets cleared on every reboot. Contents of root directory (/) are extracted from another partition named boot which contains kernel and ramdisk (though things have changed with system-as-root). So you can't change init.rc permanently unless you extract, modify, repack and reflash boot.img.

But to define a new init service, modifying init.rc isn't necessary. Android parses all .rc files from /etc/init directories located under /system and /vendor (6). So you can create your own .rc file.


NOTE: In order to get real root privileges and to deal with SELinux, all of the options given below depend on Magisk. See this answer for details.

INIT.D SCRIPT

You can use traditional init.d-like feature of Magisk to start a process on boot. Create script /data/adb/service.d/custom.sh:

#!/system/bin/sh  # write log file if executable throws something at stdout/sterr exec >>/data/media/0/executable.log 2>&1  # run script in background to avoid blocking boot chain [ -n "$BG" ] || { BG=Y "$0" & exit; }  # try to ignore signals as much as possible for i in $(seq 64); do trap '' "$i"; done  # execute script whenever exits e.g. when executable gets killed trap "sleep 5; exec $0" EXIT  # avoid multiple instances e.g. if script killed but executable is running pkill -9 -x /system/bin/executable  # execute the binary, should run in foreground, otherwise get in loop echo "$(date): Starting program..." /system/bin/executable  # program is killed, won't reach here if script is killed echo "$(date): Re-executing script..." 

* EXIT is shell's pseudo-signal.
* Android's /system/bin/pkill (from toybox) is buggy, better use busybox applet.

Place the executable under /system/bin and set permissions:

~# chown 0.0 /system/bin/executable /data/adb/service.d/custom.sh ~# chmod 0755 /system/bin/executable /data/adb/service.d/custom.sh 

You can also place script under /data/adb/post-fs-data.d/ but that's executed a bit earlier. Be sure that filesystem paths (and other required resources if any) are available at that stage.

EXECUTE PROGRAM FROM INIT

Another way is to directly execute the binary from init. Create custom.rc file:

#/etc/init/custom.rc  # execute the binary when boot is completed on property:sys.boot_completed=1     exec_background u:r:magisk:s0 -- /system/bin/executable 

Set permissions:

~# chown 0.0 /etc/init/custom.rc ~# chmod 0644 /etc/init/custom.rc ~# chcon u:object_r:system_file:s0 /etc/init/custom.rc 

And that's all! Restart device for changes to take effect.

However it's a one time execution, won't be restarted. Also there are some shell scripting features not available in .rc files. For instance you can't redirect stdout/stderr to a file, this has to be handled by executable program itself. So we can try to make use of both; shell script and .rc file:

INIT SERVICE

Instead of directly executing binary from .rc file, execute a shell script. Create script /system/bin/custom.sh:

#!/system/bin/sh  # write log file if executable throws something at stdout/sterr exec >>/data/media/0/executable.log 2>&1  # execute the binary, should run in foreground, otherwise get in loop echo "$(date): Starting program..." exec /system/bin/executable 

Create init service:

#/etc/init/custom.rc  # define service, use executable here if script not needed service custom /system/bin/custom.sh      # don't start unless explicitly asked to     disabled      # only execute once, don't restart if exited     # don't add if you want to restart service when killed     #oneshot      # run with unrestricted SELinux context to avoid avc denials     # it's required if SELinux is enforcing and service needs access     # to some system resources not allowed by default sepolicy     seclabel u:r:magisk:s0  # start the service when boot is completed on property:sys.boot_completed=1     start custom 

Set permissions on executable, custom.sh and custom.rc as stated above and restart.

Other parameters (7) such as user, group, capabilities are required if you want to run the service as non-privileged user. Granting least required privileges is the recommended approach from security's perspective. See this answer for more details on capabilities and SELinux.

init will keep on restarting service every 5 seconds (by-default) if it gets killed. You can stop the service with setprop ctl.stop custom. Replace stop with start to start again.
To see what happens with service: dmesg | grep init: | tail.

RELATED:

  • How to run an Android init service with superuser SELinux context?
  • How to run a script in background from adb shell?
 
 
 
 

相关问题

0  删除init.d中的脚本  ( Remove the script in init d ) 
我想向我的rooted android 4.2设备闪光灯。但之前,我必须删除init.d中的所有脚本。我尝试过使用Univernal Init.d来删除它们,但它们不会。任何人都可以提供帮助? ...

4  如何使用init.d文件夹创建启动脚本?  ( How to create start up scripts using the init d folder ) 
在这个回答我刚刚提出的问题,他说它有可能执行脚本每一个启动。 我创建了一个包含以下内容的文件(无扩展): #!/system/bin/sh busybox mount -o bind /emmc/Android/data/com.google.android.music/ /sdcard/Android/dat...

0  在Termux App终端访问中,我应该将自己的runnit服务置于手机重新引导时?  ( On a termux app terminal access where should i put my own runnit service to star ) 
我写了一个如此简单的服务: http://smarden.org/runit/ runscripts.html#apache2 $ cat start_node_exporter #!/data/data/com.termux/files/usr/bin/sh termux-wake-lock . $PRE...

1  init.rc无法在启动完成的事件上启动我的服务  ( Init rc doesnt start my service on boot completed event ) 
我已将以下代码段添加到 /system/core/rootdir/init.rc 文件的末尾。 on property:dev.bootcomplete=1 start bootcomplete_handler service bootcomplete_handler /system/bin/bc_ha...

3  init.d不会被执行  ( Init d doesnt get executed ) 
我正在使用三星S2和自定义ROM,外部SD卡安装到/ emmc,但我希望它挂载到/ MNT / SDCARD / EXTERNAL_SD,我如何使用init.d挂载它? 我使一个名为"99mount" 的文件,内容 mount -o bind /emmc /mnt/sdcard/external_sd 但是...

2  selinux可防止我的init.rc exec命令执行  ( Selinux prevents my init rc exec command to execute ) 
我在 init.rc 文件的末尾添加了 exec 命令。 on property:dev.bootcomplete=1 exec u:r:shell:s0 shell shell -- /system/bin/am start -n com.example.package/com.example.pack...

0  是否可以在init.d中启动无限循环?  ( Is it possible to start an infinite loop within init d ) 
我想创建一个init.d脚本,以控制棒棒糖5.1.1,cyanogenmod 12.1下的oomroid xu3的风扇。 我已经在Linux上制作了一个,它正好工作,并希望将其移植到Android。 脚本是一个无限循环,每5秒处于活动状态。是能够使用无限循环的Android init.d模块将其绘制设备吗? ...

1  Huawei U8350上的Automount Ext2 SD卡(Android 2.2.2)  ( Automount ext2 sd card on huawei u8350 android 2 2 2 ) 
在huawei u8350(android 2.2.2)上init脚本似乎都在根分区中 - 实际上是一个RAM磁盘(initRamfs),因此在重新启动中没有持久的任何更改。 是否有一种方法可以在引导时运行命令,以在外部SD上安装ext2分区,而不打开包装并重新刷新根图像? ...

3  如何在启动时运行可执行文件并将其保持运行?  ( How to run an executable on boot and keep it running ) 
我有一个来自 ndk-build 程序的可执行构建。我想在rooted android设备上运行它。 Android将杀死我可执行的可能性是多少? 使用 adb shell ,我能够使用以下命令执行我的可执行文件: adb push executable /sdcard adb shell device:/ $ ...

2  in /data/local/userinit.sh in worw  ( Mount in data local userinit sh is not working ) 
我想映射/ sdcard / dcim到/ story / sdcard1 / dcim 在I9100上使用cm 12.1 我将那些几行写为 /data/local/userinit.sh : #!/system/bin/sh log -p i -t userinit "userinit start"; mou...




© 2022 it.wenda123.org All Rights Reserved. 问答之家 版权所有