[DEV][SCRIPT] Enhanced init.d support

Search This thread

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
Okay, I worked a bit on something to add a little more options to init.d scripts for my ROM's. I came up with the below solution and thought I should share it with whomever would like a bit more options in their own ROM's. This is a first draft so some of things can properly be done in other ways, but it works and it does add a lot more options when building startup scripts while it is compatible with regular init.d scripts as well. But fell free to pitch in with ideas if you like.

Note that this thread is directed to ROM cookers, but can be used by anyone that knows how to edit ramdisk's.

So there are several problems with the regular init.d methods. First of all there are two different ways of executing the scripts and it differs from ROM to ROM which method has been implemented. We have the "exec /system/bin/sysinit" which will execute all of the scripts before continuing with the normal boot and we have the service sysinit which will execute all scripts while the normal boot is running. Both are useful for different things but no ROM has both.

Also init.d will just start executing the scripts before/during the normal boot, depended on the method, but what if we need it to execute something at a specific time during boot. Before folder structures and such are created in /data? Or when the phone has completely booted into the GUI. Or before the phone is turned off and so on.

This method will implement different states where different parts of a script can be executed depended on where in the boot process we are. All it requires is a more extended sysinit file and a couple of extra lines in the init.rc file.

File: /init.rc
Code:
on early-init
    ##
    # Whatever goes here
    ##

on init
    ##
    # Whatever goes here
    ##

on fs
    ##
    # Mount /system
    ##

    # Make sure that we have the synlinks we need to use sysinit
    symlink /system/bin/sysinit /system/bin/sysinit.onstart
    symlink /system/bin/sysinit /system/bin/sysinit.onfs
    symlink /system/bin/sysinit /system/bin/sysinit.onpostfs
    symlink /system/bin/sysinit /system/bin/sysinit.onpostfsdata
    symlink /system/bin/sysinit /system/bin/sysinit.onboot
    symlink /system/bin/sysinit /system/bin/sysinit.onsysinit
    symlink /system/bin/sysinit /system/bin/sysinit.onfinalize
    symlink /system/bin/sysinit /system/bin/sysinit.oncomplete
    symlink /system/bin/sysinit /system/bin/sysinit.onshutdown

    exec /system/bin/sysinit.onstart

    ##
    # Mount the rest of the partitions and remount /system without write permissions
    ##

    exec /system/bin/sysinit.onfs

on post-fs
    ##
    # Whatever goes here
    ##

    exec /system/bin/sysinit.onpostfs

on post-fs-data
    ##
    # Whatever goes here
    ##

    exec /system/bin/sysinit.onpostfsdata

    ##
    # If you want to include an additional *.rc file, do it here at the end of post-fs-data
    ##

on boot
    ##
    # Whatever goes here
    ##

    exec /system/bin/sysinit.onboot

    start sysinit

    ##
    # Start any other services
    ##

on property:init.svc.bootanim=stopped
    start syscomplete

on property:sys.boot_completed=1
    exec /system/bin/sysinit.onfinalize

on property:sys.shutdown.requested=1
    exec /system/bin/sysinit.onshutdown

service sysinit /system/bin/sysinit.onsysinit
    disabled
    oneshot

service syscomplete /system/bin/sysinit.oncomplete
    disabled
    oneshot

##
# The rest of the file
##

File: /system/bin/sysinit
Code:
#!/system/bin/sh

export PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin

if [ -d /system/etc/init.d ]; then
	case $(basename $0) in 
		"sysinit") INIT_STATE="$1" ;;
		*) INIT_STATE="`basename $0 | cut -d '.' -f2`" ;;
	esac

	while :
	do
		if [ ! -f /sysinit.stage.prop ]; then
			mount -o remount,rw /
			touch /sysinit.stages.prop
			mount -o remount,ro /
		fi

		if ( [ "$INIT_STATE" != "onfinalize" ] && [ "$INIT_STATE" != "oncomplete" ] ) || ( [ "$INIT_STATE" = "onfinalize" ] && [ ! -z "`grep onpostsysinit /sysinit.stages.prop`" ] ) || ( [ "$INIT_STATE" = "oncomplete" ] && [ ! -z "`grep onfinalize /sysinit.stages.prop`" ] ); then
			if [ "$INIT_STATE" = "onsysinit" ]; then
				RUN_STATES="onsysinit onpostsysinit"; sleep 1

			elif [ "$INIT_STATE" = "oncomplete" ]; then
				RUN_STATES="onservice oncomplete"

			else
				RUN_STATES="$INIT_STATE"
			fi

			for x in $RUN_STATES; do
				log -p v -t sysinit "Switching to state '$x'..."

				case $x in 
					# Make it compatible with old init scripts
					onboot|"") FILES="`find /system/etc/init.d -type f | sort`" ;;
					*) FILES="`find /system/etc/init.d -type f -iname '*.rc' | sort`" ;;
				esac

				for i in $FILES; do
					if [ ! -d $i ] && [ -x $i ]; then
						log -p v -t sysinit "Executing $i..."
			
						if [ "$x" = "onservice" ]; then
							logwrapper $i $x > /dev/null &
						else
							logwrapper $i $x
						fi

					else
						log -p w -t sysinit "Skipping $i. Not an executable!"
					fi
				done

				mount -o remount,rw /
				echo $x >> /sysinit.stages.prop
				mount -o remount,ro /
			done

			break
		fi

		sleep 1
	done
fi

To use this you need to end the names of your init script with .rc like "55<name>.rc" instead of just "55<name>". This is to keep it compatible with regular init.d scripts.

This will allow you to build init.d scripts like this
Code:
#!/system/bin/sh

case $1 in
	onstart)
		# Do something right after the system partition has been mounted RW (No other partitions at this time)
	;;

	onfs)
		# Do something right after the rest of partitions has been mounted and system has been remounted RO, before any of them are used or changed in any way.
	;;

	onpostfs)
		# This is almost the same as onfs, only minor changes has normally been made here
	;;

	onpostfsdata)
		# Do something after the /data partition has been rebuild with folders, permission, ownership and so on
	;;

	onboot)
		# Do something right before Android starts booting and it's services are triggered
	;;

	onsysinit)
		# Do something while Android is booting. This will NOT stall the boot process but run along side it
	;;

	onpostsysinit)
		# Do something as soon as onsysinit has finished
	;;

	onfinalize)
		# Do something when the system is almost booted, this also includes the sysinit parts above
	;;

	onservice)
		# Do some constant work in the background (Service/Daemon)
	;;

	oncomplete)
		# Do something when the phone is fully booted and the boot animation is gone
	;;

	onshutdown)
		# Do something before the phone is turned off or rebooted
	;;
esac


EDIT 1
  • Added 'onfinalize' which is actually the old oncomplete. The new oncomplete runs as a service like onsysinit and onpostsysinit to ensure that you are able to use things like "sleep" without stalling the system.
  • Rewrote sysinit, much cleaner now

EDIT 2
  • Added 'onservice' which can be used to run a constant task in the background after the phone has booted
 
Last edited:

jayallen1980

Senior Member
Oct 20, 2011
139
17
Awesome great work. The last line say do comething before the phone is turned off or rebooted. is it suppose to say something.

Sent from my HTC Desire CDMA using Tapatalk 2
 

varun.chitre15

Inactive Recognized Developer
Oct 23, 2011
3,153
15,403
Sangli
Some examples would be good :)
Can you please? :D(Example of Executing Juwe's RAM script will be nice in all cases)
What if I want to keep init.d folder empty and integrate my scripts inside boot.img? and then execute them inside it?
 

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
Some examples would be good :)
Can you please? :D(Example of Executing Juwe's RAM script will be nice in all cases)
What if I want to keep init.d folder empty and integrate my scripts inside boot.img? and then execute them inside it?

Why would you integrate scripts into the boot.img? The point of init.d is to be able to add things to boot without changing the boot.img. If you want to execute things from within the boot.img, then just place your scripts in it (sbin would be a good place) and execute it the same way my example executes /system/bin/sysinit.

And as for examples, it's easy. Just place your code in that section (onboot, onfs etc) where you want the code to be executed. The onboot is the default in process in most ROM's and also where regular init.d scripts is executed in this example.
 
  • Like
Reactions: varun.chitre15

eugene373

Retired Recognized Developer
Aug 11, 2009
5,844
7,424
eb-productions.proboards.com
Why would you integrate scripts into the boot.img? The point of init.d is to be able to add things to boot without changing the boot.img. If you want to execute things from within the boot.img, then just place your scripts in it (sbin would be a good place) and execute it the same way my example executes /system/bin/sysinit.

And as for examples, it's easy. Just place your code in that section (onboot, onfs etc) where you want the code to be executed. The onboot is the default in process in most ROM's and also where regular init.d scripts is executed in this example.

because the point of this is to start scripts when you want.. there is a few scripts I have that can't be ran until os is loaded, there for making this a great setup for me.

init.d & boot.img runs everything at boot... not after boot.
 

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
because the point of this is to start scripts when you want.. there is a few scripts I have that can't be ran until os is loaded, there for making this a great setup for me.

init.d & boot.img runs everything at boot... not after boot.

The 'oncomplete' runs everything when the system is fully loaded, that's the point of this init.d system, to be able to run scripts in different ways during different stages.
 
  • Like
Reactions: Titchener17

eugene373

Retired Recognized Developer
Aug 11, 2009
5,844
7,424
eb-productions.proboards.com
The 'oncomplete' runs everything when the system is fully loaded, that's the point of this init.d system, to be able to run scripts in different ways during different stages.

yeah I got it..... I've been having one hell of a time starting script until I cam across this...

If it starts like a normal init.d file it hangs the boot process... with this edit I can trigger it to run on bootcomplete with out hanging the service :)

sorry, I just noticed I quoted you and not the other guy :(
 

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
yeah I got it..... I've been having one hell of a time starting script until I cam across this...

If it starts like a normal init.d file it hangs the boot process... with this edit I can trigger it to run on bootcomplete with out hanging the service :)

sorry, I just noticed I quoted you and not the other guy :(

Yes oncomplete, oninit and onservice will not stall the process, oninit will however stall onfinalize, oncomplete and onservice. onservice will run the script in a seperate process in the background, so that will not even stall the rest of the init.d scripts while executing, making that great for scripts that should keep running, or where you don't know how long they should run.
 

eugene373

Retired Recognized Developer
Aug 11, 2009
5,844
7,424
eb-productions.proboards.com
Yes oncomplete, oninit and onservice will not stall the process, oninit will however stall onfinalize, oncomplete and onservice. onservice will run the script in a seperate process in the background, so that will not even stall the rest of the init.d scripts while executing, making that great for scripts that should keep running, or where you don't know how long they should run.

Adding this into all my boot.img from now on & I'll be sure to link this thread...

I think this should be the new standard for all Devs, this method is not only a great idea!

But for the End User, there's so much more control over what can / should be done on starting process...

I personally want to thank you for this, as this truely is one of the better methods I've ever seen!!

~Eugene
 

hashnon

Senior Member
Oct 19, 2006
79
12
HTC Leo
Moto Z2 Force
dk_zero-cool, I'd like to ask you, why you use soft-links and not parameters?
It will remove all
Code:
symlink /system/bin/sysinit /system/bin/sysinit.*
from init.rc and you will not need to use case in sysinit.
Because this whole construction:
Code:
case $(basename $0) in 
	"sysinit") INIT_STATE="$1" ;;
	*) INIT_STATE="`basename $0 | cut -d '.' -f2`" ;;
esac
seems to me like overload.
 
Last edited:

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
dk_zero-cool, I'd like to ask you, why you use soft-links and not parameters?
It will remove all
Code:
symlink /system/bin/sysinit /system/bin/sysinit.*
from init.rc and you will not need to use case in sysinit.
Because this whole construction:
Code:
case $(basename $0) in 
	"sysinit") INIT_STATE="$1" ;;
	*) INIT_STATE="`basename $0 | cut -d '.' -f2`" ;;
esac
seems to me like overload.

Because I have had bad experience using arguments along with the exec command, so I try to avoid that. Mostly because I can't remember the issues anymore.

As for overload, this is to small to be noticed, specially when this is only executed a couple of times during startup. If this was to be executed every couple of minute during the phone on state, then sure. But when the phone has booted, sysinit is no longer used.
 
  • Like
Reactions: Titchener17

Kaskade

Senior Member
Aug 14, 2011
101
41
In the kernel ramdisk of my Xperia ray, there are two kinds of inits, init.rc and init.semc.rc.
The "on fs" exists in init.semc.rc (where i can see the commands to mount the partitions). In init.rc there's no "on fs" between "on early-fs" and "on post-fs".
So i've put the "on fs"-part in init.semc.rc and the rest of your fabulous work into init.rc. When i look after booting into the /system/bin/ directory i can see all the "sysinit.on........." symlinks. Is that proof that i did everything right so far? Haven't tried any script yet to be honest.
 

dk_zero-cool

Senior Member
Nov 6, 2010
3,529
4,996
Horsens
In the kernel ramdisk of my Xperia ray, there are two kinds of inits, init.rc and init.semc.rc.
The "on fs" exists in init.semc.rc (where i can see the commands to mount the partitions). In init.rc there's no "on fs" between "on early-fs" and "on post-fs".
So i've put the "on fs"-part in init.semc.rc and the rest of your fabulous work into init.rc. When i look after booting into the /system/bin/ directory i can see all the "sysinit.on........." symlinks. Is that proof that i did everything right so far? Haven't tried any script yet to be honest.

Yes some phones have extra init files for onfs. Mostly if they use different file system types. What you did is correct in this case.

You can check the file /sysinit.stages.prop to see if all stages was executed. If one stage is missing from that file, it was not executed.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 30
    Okay, I worked a bit on something to add a little more options to init.d scripts for my ROM's. I came up with the below solution and thought I should share it with whomever would like a bit more options in their own ROM's. This is a first draft so some of things can properly be done in other ways, but it works and it does add a lot more options when building startup scripts while it is compatible with regular init.d scripts as well. But fell free to pitch in with ideas if you like.

    Note that this thread is directed to ROM cookers, but can be used by anyone that knows how to edit ramdisk's.

    So there are several problems with the regular init.d methods. First of all there are two different ways of executing the scripts and it differs from ROM to ROM which method has been implemented. We have the "exec /system/bin/sysinit" which will execute all of the scripts before continuing with the normal boot and we have the service sysinit which will execute all scripts while the normal boot is running. Both are useful for different things but no ROM has both.

    Also init.d will just start executing the scripts before/during the normal boot, depended on the method, but what if we need it to execute something at a specific time during boot. Before folder structures and such are created in /data? Or when the phone has completely booted into the GUI. Or before the phone is turned off and so on.

    This method will implement different states where different parts of a script can be executed depended on where in the boot process we are. All it requires is a more extended sysinit file and a couple of extra lines in the init.rc file.

    File: /init.rc
    Code:
    on early-init
        ##
        # Whatever goes here
        ##
    
    on init
        ##
        # Whatever goes here
        ##
    
    on fs
        ##
        # Mount /system
        ##
    
        # Make sure that we have the synlinks we need to use sysinit
        symlink /system/bin/sysinit /system/bin/sysinit.onstart
        symlink /system/bin/sysinit /system/bin/sysinit.onfs
        symlink /system/bin/sysinit /system/bin/sysinit.onpostfs
        symlink /system/bin/sysinit /system/bin/sysinit.onpostfsdata
        symlink /system/bin/sysinit /system/bin/sysinit.onboot
        symlink /system/bin/sysinit /system/bin/sysinit.onsysinit
        symlink /system/bin/sysinit /system/bin/sysinit.onfinalize
        symlink /system/bin/sysinit /system/bin/sysinit.oncomplete
        symlink /system/bin/sysinit /system/bin/sysinit.onshutdown
    
        exec /system/bin/sysinit.onstart
    
        ##
        # Mount the rest of the partitions and remount /system without write permissions
        ##
    
        exec /system/bin/sysinit.onfs
    
    on post-fs
        ##
        # Whatever goes here
        ##
    
        exec /system/bin/sysinit.onpostfs
    
    on post-fs-data
        ##
        # Whatever goes here
        ##
    
        exec /system/bin/sysinit.onpostfsdata
    
        ##
        # If you want to include an additional *.rc file, do it here at the end of post-fs-data
        ##
    
    on boot
        ##
        # Whatever goes here
        ##
    
        exec /system/bin/sysinit.onboot
    
        start sysinit
    
        ##
        # Start any other services
        ##
    
    on property:init.svc.bootanim=stopped
        start syscomplete
    
    on property:sys.boot_completed=1
        exec /system/bin/sysinit.onfinalize
    
    on property:sys.shutdown.requested=1
        exec /system/bin/sysinit.onshutdown
    
    service sysinit /system/bin/sysinit.onsysinit
        disabled
        oneshot
    
    service syscomplete /system/bin/sysinit.oncomplete
        disabled
        oneshot
    
    ##
    # The rest of the file
    ##

    File: /system/bin/sysinit
    Code:
    #!/system/bin/sh
    
    export PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
    
    if [ -d /system/etc/init.d ]; then
    	case $(basename $0) in 
    		"sysinit") INIT_STATE="$1" ;;
    		*) INIT_STATE="`basename $0 | cut -d '.' -f2`" ;;
    	esac
    
    	while :
    	do
    		if [ ! -f /sysinit.stage.prop ]; then
    			mount -o remount,rw /
    			touch /sysinit.stages.prop
    			mount -o remount,ro /
    		fi
    
    		if ( [ "$INIT_STATE" != "onfinalize" ] && [ "$INIT_STATE" != "oncomplete" ] ) || ( [ "$INIT_STATE" = "onfinalize" ] && [ ! -z "`grep onpostsysinit /sysinit.stages.prop`" ] ) || ( [ "$INIT_STATE" = "oncomplete" ] && [ ! -z "`grep onfinalize /sysinit.stages.prop`" ] ); then
    			if [ "$INIT_STATE" = "onsysinit" ]; then
    				RUN_STATES="onsysinit onpostsysinit"; sleep 1
    
    			elif [ "$INIT_STATE" = "oncomplete" ]; then
    				RUN_STATES="onservice oncomplete"
    
    			else
    				RUN_STATES="$INIT_STATE"
    			fi
    
    			for x in $RUN_STATES; do
    				log -p v -t sysinit "Switching to state '$x'..."
    
    				case $x in 
    					# Make it compatible with old init scripts
    					onboot|"") FILES="`find /system/etc/init.d -type f | sort`" ;;
    					*) FILES="`find /system/etc/init.d -type f -iname '*.rc' | sort`" ;;
    				esac
    
    				for i in $FILES; do
    					if [ ! -d $i ] && [ -x $i ]; then
    						log -p v -t sysinit "Executing $i..."
    			
    						if [ "$x" = "onservice" ]; then
    							logwrapper $i $x > /dev/null &
    						else
    							logwrapper $i $x
    						fi
    
    					else
    						log -p w -t sysinit "Skipping $i. Not an executable!"
    					fi
    				done
    
    				mount -o remount,rw /
    				echo $x >> /sysinit.stages.prop
    				mount -o remount,ro /
    			done
    
    			break
    		fi
    
    		sleep 1
    	done
    fi

    To use this you need to end the names of your init script with .rc like "55<name>.rc" instead of just "55<name>". This is to keep it compatible with regular init.d scripts.

    This will allow you to build init.d scripts like this
    Code:
    #!/system/bin/sh
    
    case $1 in
    	onstart)
    		# Do something right after the system partition has been mounted RW (No other partitions at this time)
    	;;
    
    	onfs)
    		# Do something right after the rest of partitions has been mounted and system has been remounted RO, before any of them are used or changed in any way.
    	;;
    
    	onpostfs)
    		# This is almost the same as onfs, only minor changes has normally been made here
    	;;
    
    	onpostfsdata)
    		# Do something after the /data partition has been rebuild with folders, permission, ownership and so on
    	;;
    
    	onboot)
    		# Do something right before Android starts booting and it's services are triggered
    	;;
    
    	onsysinit)
    		# Do something while Android is booting. This will NOT stall the boot process but run along side it
    	;;
    
    	onpostsysinit)
    		# Do something as soon as onsysinit has finished
    	;;
    
    	onfinalize)
    		# Do something when the system is almost booted, this also includes the sysinit parts above
    	;;
    
    	onservice)
    		# Do some constant work in the background (Service/Daemon)
    	;;
    
    	oncomplete)
    		# Do something when the phone is fully booted and the boot animation is gone
    	;;
    
    	onshutdown)
    		# Do something before the phone is turned off or rebooted
    	;;
    esac


    EDIT 1
    • Added 'onfinalize' which is actually the old oncomplete. The new oncomplete runs as a service like onsysinit and onpostsysinit to ensure that you are able to use things like "sleep" without stalling the system.
    • Rewrote sysinit, much cleaner now

    EDIT 2
    • Added 'onservice' which can be used to run a constant task in the background after the phone has booted
    2
    yeah I got it..... I've been having one hell of a time starting script until I cam across this...

    If it starts like a normal init.d file it hangs the boot process... with this edit I can trigger it to run on bootcomplete with out hanging the service :)

    sorry, I just noticed I quoted you and not the other guy :(

    Yes oncomplete, oninit and onservice will not stall the process, oninit will however stall onfinalize, oncomplete and onservice. onservice will run the script in a seperate process in the background, so that will not even stall the rest of the init.d scripts while executing, making that great for scripts that should keep running, or where you don't know how long they should run.
    2
    In the kernel ramdisk of my Xperia ray, there are two kinds of inits, init.rc and init.semc.rc.
    The "on fs" exists in init.semc.rc (where i can see the commands to mount the partitions). In init.rc there's no "on fs" between "on early-fs" and "on post-fs".
    So i've put the "on fs"-part in init.semc.rc and the rest of your fabulous work into init.rc. When i look after booting into the /system/bin/ directory i can see all the "sysinit.on........." symlinks. Is that proof that i did everything right so far? Haven't tried any script yet to be honest.

    Yes some phones have extra init files for onfs. Mostly if they use different file system types. What you did is correct in this case.

    You can check the file /sysinit.stages.prop to see if all stages was executed. If one stage is missing from that file, it was not executed.
    1
    Some examples would be good :)
    Can you please? :D(Example of Executing Juwe's RAM script will be nice in all cases)
    What if I want to keep init.d folder empty and integrate my scripts inside boot.img? and then execute them inside it?

    Why would you integrate scripts into the boot.img? The point of init.d is to be able to add things to boot without changing the boot.img. If you want to execute things from within the boot.img, then just place your scripts in it (sbin would be a good place) and execute it the same way my example executes /system/bin/sysinit.

    And as for examples, it's easy. Just place your code in that section (onboot, onfs etc) where you want the code to be executed. The onboot is the default in process in most ROM's and also where regular init.d scripts is executed in this example.
    1
    because the point of this is to start scripts when you want.. there is a few scripts I have that can't be ran until os is loaded, there for making this a great setup for me.

    init.d & boot.img runs everything at boot... not after boot.

    The 'oncomplete' runs everything when the system is fully loaded, that's the point of this init.d system, to be able to run scripts in different ways during different stages.