I'm accustomed to running scripts on boot in Linux, but I'm not sure how to do this in Android. I'd like to start my SSH daemon on start, so I'll always be able to connect. How can I run an arbitrary script on Android boot? It'd be preferable to do this outside of Dalvik.
9 Answers
While looking around my Android filesystem, I found that it did, in fact have a /etc/init.d/
directory. After peeking around in there, I found /etc/init.d/20userinit
with the following lines:
if [ -e /data/local/userinit.sh ];
then
log -p -i -t userinit "Executing /data/local/userinit.sh";
busybux chmod +x /data/local/userinit.sh;
logwrapper /system/bin/sh /data/local/userinit.sh;
setprop cm.userinit.active 1;
fi;
This being, of course, exactly what I needed, I wrote the following script on my computer then pushed it to my device:
#!/system/bin/sh
dropbear -s -g
(pushed to device via scp userinit.sh phone:/data/local/userinit.sh
, mind you :] )
Rebooted the device, then ran ps | grep "[d]ropbear"
, and sure enough, it's running. Coolness!
-
Comments are not for extended discussion; this conversation has been moved to chat.– Firelord ♦Commented Oct 22, 2019 at 8:22
-
it seams lineageos comes with a
90userinit
exatcly like that. Thanks a lot for the hint!– imbrCommented Mar 30, 2021 at 17:49 -
2but better use magisk github.com/topjohnwu/Magisk/blob/master/docs/…– imbrCommented Apr 13, 2021 at 13:20
/data/init.sh
runs at boot, if you have root you can edit it as you like. Be careful ;)
Edit: Apparently you might need to shoehorn the edited script into the boot image as well. Info on how to do that here: http://forum.xda-developers.com/showthread.php?t=443994
-
1Yeah, I can't seem to find this file on my Nexus One running CM7-RC1. I'll see if a
find / -name "init.sh"
turns anything up. Are there any other scripts that run on boot? Commented Mar 2, 2011 at 21:32 -
1You should have an
/etc/init.rc
which starts the shell. It should call init.sh but if it doesn't you can just make it call your own script. Commented Mar 2, 2011 at 21:40 -
Unfortunately, I don't have that script either, but I did find a solution. Commented Mar 2, 2011 at 21:49
-
3What version of Android is it ? 4.3 does have
/data
but no/data/init/.sh
or/etc/init.rc
. Grep does not find any interesting instance of the stringinit
in/etc
(even recursive). Commented Dec 7, 2013 at 18:32
If you have Magisk installed you can place the .sh to:
/sbin/.magisk/img/.core/service.d/
or to
/sbin/.magisk/img/.core/post-fs-data.d/
Don't forget to make it executable: chmod +x your-script.sh
.
More info: https://github.com/topjohnwu/Magisk/blob/master/docs/guides.md#boot-scripts
-
1
Look to /etc/
directory. Usually it is placed in /system/
partition which you can mount as RW:
$ ls -l /etc
lrwxrwxrwx 1 root root 11 Jan 1 2009 /etc -> /system/etc
$ su
$ mount -o remount,rw /system
$ chmod o+w /system/etc # for "adb push"
Some above steps may be replaces with:
$ adb root
$ adb remount
and later remount RO:
$ chmod o-w /system/etc
$ mount -o remount,ro /system
Now your task to find executable or *rc
file which you modify to achieve your goal:
$ find /etc -type f -perm +110
$ find /etc -name "*rc"
$ find /etc -name "init*"
$ grep -R /data /etc
$ grep -R /system /etc
Google about each candidate to get know how this file was used.
Good candidate for including custom scripts are lines from:
$ grep service /init*.rc
As each device unique you may need to do own guess about search criteria...
For example I found /etc/mkshrc
which used by Korn shell. I update this file to extend PATH
env var and now each time I do adb shell
I have Busybox symlinks in my PATH!
See also hard way (if you have no luck with finding magic file): https://stackoverflow.com/questions/9768103/make-persistent-changes-to-init-rc
-
But isn't it getting overriden every boot ? I think the /etc folder is part of cpio which is ramdisk.– ranshCommented Dec 18, 2016 at 17:09
-
1@ransh this is not the case at least in: 8.1.0_r60 where
/system
issystem.img
, and/etc
is a symlink into/system
. Commented Jan 31, 2019 at 10:48 -
I found that even after deleting a file from
/system
I was unable to put it back (the same file) because of "no space left on device". Of course the system image has the exact size it needs but I don't know why deleting the file didn't free its space. (It wasn't the open file descriptors thing.)– AndreKRCommented Nov 16, 2022 at 0:02
I tried all these methods and none of them worked for me. What worked however was based on lord-ralf-adolf's answer here How to run a script on boot in CM12.1?
basically, find the file
/system/etc/install-recovery.sh
and add the following line at the beginning
/data/init.sh &
then
touch /data/init.sh
chmod 755 /data/init.sh
Done!
You can now put whatever you want in /data/init.sh
and it will run on startup.
If the file /system/etc/install-recovery.sh
is not in your system then this answer won't work for you. Don't bother creating it.
-
4Actually, I have a system where
/system/etc/install-recovery.sh
was not present, but it is still executed on boot if present, so it's worth checking.– jcaronCommented Aug 8, 2018 at 22:25 -
1
Things were simple before Android 5 when SELinux wasn't enforcing
. You could put your code in any script or replace a binary with script which was executed with root privileges on boot. Another method was to define a custom init
service specifically to batch execute scripts from some directory.
Based on these approaches custom ROM developers introduced different pseudo-init.d
phenomenon like /etc/init.d/
, /etc/install-recovery.sh
, /etc/init.qcom.post_boot.sh
, /system/bin/debuggerd
, /data/init.sh
, /data/local/userinit.sh
, /data/local/init.d/
etc.
However a process running with UID 0
but in a restricted SELinux context is quite helpless. A service started in init.rc
file with u:r:init:s0
context can't even execute a shell script from /system/bin/
, so SELinux policy needs to be patched to inject an unrestricted context e.g. Magisk defines u:r:magisk:s0
. After that it's possible to run a script directly as init
service or from init.d
-like directory.
For details see How to run an executable on boot and keep it running?
Simple way (working):
Prepare your post-boot commands in a script, say
/system/xbin/post-boot
(set exec perm)Add the above custom script path at the end of
/system/etc/init.qcom.post_boot.sh
, e.g.# echo /system/xbin/post-boot >> /system/etc/init.qcom.post_boot.sh
Done!
(If you can't find the qcom.post_boot.sh
(Qualcomm devices), look for any post_boot
scripts)
This ROOT method works for 4.1.1 Jellybean, and would probably work for other versions as well. There is a fantastic app called init.d scripts support by RYO Software (com.ryosoftware.initd). Make sure you have 'Try to acquire root privileges'
checked. Permissions for startup script are 0055
, ownership system.sdcard_rw
. Permissions/Ownership of startup script can probably be left to defaults.
If you try to run your script indefinitely in your main script, it won't work. But there is a way to do it:
Put this somewhere in your main startup script:
sh /data/BackgroundScript.sh &
Then make sure permissions and ownership are right:
chmod 0755 /data/BackgroundScript.sh
chown root.root /data/BackgroundScript.sh
/system/etc/install-recovery.sh
does not exist but /system/bin/install-recovery.sh
does. Append your executable instructions to the end of this script to execute those instructions during boot.