Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Prodo123

macrumors 68020
Original poster
Nov 18, 2010
2,326
10
Hi,

I'm trying to automate a relatively simple RAM disk script using launchd. The original script can be found here, except I also added the directories /private/tmp and /var/run. As Startup Items are not run as root and have been deprecated, I attempted to launch the script using a launchd plist.

launchd runs the script, but it continues to run it, creating multiple RAM disks until all memory is consumed (...). I have to manually unload the plist before memory runs out. How do I make launchd run the script just once?

I also have a second script to replace the soft links created by the RAM disk script with actual empty folders, otherwise the system kernel panics. It's intended to run only when the system shuts down; as such I have the script trapping the signal SIGTERM. But it doesn't work.

Can someone help me out? Thanks!
 

Attachments

  • Logout.zip
    717 bytes · Views: 270

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
Hi,

I'm trying to automate a relatively simple RAM disk script using launchd. The original script can be found here, except I also added the directories /private/tmp and /var/run. As Startup Items are not run as root and have been deprecated, I attempted to launch the script using a launchd plist.

launchd runs the script, but it continues to run it, creating multiple RAM disks until all memory is consumed (...). I have to manually unload the plist before memory runs out. How do I make launchd run the script just once?

You have to post the plist file, you may use the wrong key, or something else. It's also probably not a good idea to mess with /private/tmp and /var/run, what makes you think that's an optimization to begin with btw, they contain mostly sockets which are not physical files.

I also have a second script to replace the soft links created by the RAM disk script with actual empty folders, otherwise the system kernel panics. It's intended to run only when the system shuts down; as such I have the script trapping the signal SIGTERM. But it doesn't work.

Can someone help me out? Thanks!

Trap will not make your script run at shut down, the trap catches the SIGTERM signal and executes the given function provided that the script is already running. It's intended to prevent someone to kill your program before you do cleanup of files for example, in this case the script is not running, you will need launchd for the logout as well. But, you probably shouldn't mess with those system folders anyway so the point may be moot.
 

Prodo123

macrumors 68020
Original poster
Nov 18, 2010
2,326
10
You have to post the plist file, you may use the wrong key, or something else. It's also probably not a good idea to mess with /private/tmp and /var/run, what makes you think that's an optimization to begin with btw, they contain mostly sockets which are not physical files.



Trap will not make your script run at shut down, the trap catches the SIGTERM signal and executes the given function provided that the script is already running. It's intended to prevent someone to kill your program before you do cleanup of files for example, in this case the script is not running, you will need launchd for the logout as well. But, you probably shouldn't mess with those system folders anyway so the point may be moot.

Here you go:
http://blog.bluezucchini.com/2012/11/fixing-script-execution-on-ramfs.html
http://blog.alutam.com/2012/04/01/optimizing-macos-x-lion-for-ssd/#ramdisk
http://blog.philippklaus.de/2011/04/ssd-optimizations-on-mac-os-x/
https://docwhat.org/two-ways-to-improve-os-x/

And that's exactly what I intend the trap to do: cleanup after the RAMdisk before shutting down.
I tried manually loading the plist (and in theory the script) with launchctl to no effect.

The plists are extremely basic with just a label, ProgramArguments pointing to the shell script directory and a KeepAlive flag (which doesn't do anything; I might as well remove it). They are attached with this post.
 

Attachments

  • plist.zip
    1.8 KB · Views: 280

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
Here you go:
http://blog.bluezucchini.com/2012/11/fixing-script-execution-on-ramfs.html
http://blog.alutam.com/2012/04/01/optimizing-macos-x-lion-for-ssd/#ramdisk
http://blog.philippklaus.de/2011/04/ssd-optimizations-on-mac-os-x/
https://docwhat.org/two-ways-to-improve-os-x/

And that's exactly what I intend the trap to do: cleanup after the RAMdisk before shutting down.
I tried manually loading the plist (and in theory the script) with launchctl to no effect.

A trap does not work like you think it does, the script must be running for it to have any effect, it's not running.

The plists are extremely basic with just a label, ProgramArguments pointing to the shell script directory and a KeepAlive flag (which doesn't do anything; I might as well remove it). They are attached with this post.

Use the code tags (the # symbol in the post editor).
 

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
Also, if the temp files are not accessed often or are very large it's no point in moving them to a ramdisk, in this case they are not real files anyway they are sockets which you can think of as communication channels. To test files that are accessed often you need to profile the system, there are many temporary files except these folders anyway.
 

Prodo123

macrumors 68020
Original poster
Nov 18, 2010
2,326
10
Also, if the temp files are not accessed often or are very large it's no point in moving them to a ramdisk, in this case they are not real files anyway they are sockets which you can think of as communication channels. To test files that are accessed often you need to profile the system, there are many temporary files except these folders anyway.

1. I'm trying to reduce I/O operations, not disk use. SSD wear comes from frequent write operations and moving caches to a RAM disk solves that problem, even if the files are "not real files" as some data does get written to that directory.

2. Can you just help me get the scripts working?
 

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
The plists are extremely basic with just a label, ProgramArguments pointing to the shell script directory and a KeepAlive flag (which doesn't do anything; I might as well remove it). They are attached with this post.

I will post it inline here for a reference.

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.prodo123.RAMDisk</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Volumes/Macintosh HD/Users/Laptop/.scripts/Ramdisk.sh</string>
	</array>
	<key>KeepAlive</key>
	<true/>
</dict>
</plist>

The KeepAlive key is used to control if launchd should act as a watch dog and make sure the script runs forever, your script should run once and quit so you should use the RunAtLoad key.

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.prodo123.RAMDiskExit.plist</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Volumes/Macintosh HD/Users/Laptop/.scripts/Logout.sh</string>
	</array>
	<key>KeepAlive</key>
	<true/>
</dict>
</plist>

Similarly here, your script should not set KeepAlive to true but use the RunAtLoad key. The other issue is that your logout script contains nothing but a signal handler and will therefore quit immediately, there is nothing in the script.




And here's the logout script:

Code:
#!/bin/bash

trap shutdownStuff SIGTERM

shutdownStuff()
{
# commands to call during shutdown
rm -rf /private/tmp
rm -rf /var/run
rm -rf /Users/Laptop/Library/Caches/com.apple.Safari
rm -rf /Users/Laptop/Library/Caches/com.apple.iTunes
mkdir /private/tmp
mkdir /var/run
mkdir /Users/Laptop/Library/Caches/com.apple.Safari
mkdir /Users/Laptop/Library/Caches/com.apple.iTunes
chmod 755 /private/tmp
chmod 755 /var/run
}


----------

1. I'm trying to reduce I/O operations, not disk use. SSD wear comes from frequent write operations and moving caches to a RAM disk solves that problem, even if the files are "not real files" as some data does get written to that directory.

You will not reduce I/O operations, the disk is not involved in the I/O at all except to hold the socket handle (true for the sockets). How frequent are read and writes to these extra directories, have you checked. I'm not referring to the caches for the browsers btw.
 

Prodo123

macrumors 68020
Original poster
Nov 18, 2010
2,326
10
The KeepAlive key is used to control if launchd should act as a watch dog and make sure the script runs forever, your script should run once and quit so you should use the RunAtLoad key.

Will try with RunAtLoad.

The other issue is that your logout script contains nothing but a signal handler and will therefore quit immediately, there is nothing in the script.

How about this:

Code:
#!/bin/bash

function shutdownStuff
{
# commands to call during shutdown
rm -rf /private/tmp
rm -rf /var/run
rm -rf /Users/Laptop/Library/Caches/com.apple.Safari
rm -rf /Users/Laptop/Library/Caches/com.apple.iTunes
mkdir /private/tmp
mkdir /var/run
mkdir /Users/Laptop/Library/Caches/com.apple.Safari
mkdir /Users/Laptop/Library/Caches/com.apple.iTunes
chmod 755 /private/tmp
chmod 755 /var/run
}

trap shutdownStuff SIGTERM
while :
do sleep infinity
done

You will not reduce I/O operations, the disk is not involved in the I/O at all except to hold the socket handle (true for the sockets). How frequent are read and writes to these extra directories, have you checked. I'm not referring to the caches for the browsers btw.

Obviously enough to warrant them a space on the RAM.
 
Last edited:

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
How about this:

Code:
#!/bin/bash

function shutdownStuff
{
# commands to call during shutdown
rm -rf /private/tmp
rm -rf /var/run
rm -rf /Users/Laptop/Library/Caches/com.apple.Safari
rm -rf /Users/Laptop/Library/Caches/com.apple.iTunes
mkdir /private/tmp
mkdir /var/run
mkdir /Users/Laptop/Library/Caches/com.apple.Safari
mkdir /Users/Laptop/Library/Caches/com.apple.iTunes
chmod 755 /private/tmp
chmod 755 /var/run
}

trap shutdownStuff SIGTERM

From what I know the syntax for trap is
Code:
trap command signal
yet every time I run trap, even through Terminal (e.g. trap "echo hello" SIGINT), it quits (?) instantly without doing anything.

But you should not use trap, it does not work like that, it's intended for processes that keeps on running and needs to perform some actions if it's quit unexpectedly. Basically a script of this form:

Code:
while true
    do this forever

All you need is:

Code:
#!/bin/bash

# commands to call during shutdown
rm -rf /private/tmp
rm -rf /var/run
rm -rf /Users/Laptop/Library/Caches/com.apple.Safari
rm -rf /Users/Laptop/Library/Caches/com.apple.iTunes
mkdir /private/tmp
mkdir /var/run
mkdir /Users/Laptop/Library/Caches/com.apple.Safari
mkdir /Users/Laptop/Library/Caches/com.apple.iTunes
chmod 755 /private/tmp
chmod 755 /var/run



Obviously enough to warrant them a space on the RAM.

It's not obvious at all, and from what we have seen so far you don't appear to know exactly what you are doing, yet you're performing brain surgery on the OS. I don't care about your system, I mean you can do what ever you want, but then at least it can serve as a warning for others who might read the post.
 

Prodo123

macrumors 68020
Original poster
Nov 18, 2010
2,326
10
But you should not use trap, it does not work like that, it's intended for processes that keeps on running and needs to perform some actions if it's quit unexpectedly. Basically a script of this form:

Code:
while true
    do this forever

All you need is:

Code:
#!/bin/bash

# commands to call during shutdown
rm -rf /private/tmp
rm -rf /var/run
rm -rf /Users/Laptop/Library/Caches/com.apple.Safari
rm -rf /Users/Laptop/Library/Caches/com.apple.iTunes
mkdir /private/tmp
mkdir /var/run
mkdir /Users/Laptop/Library/Caches/com.apple.Safari
mkdir /Users/Laptop/Library/Caches/com.apple.iTunes
chmod 755 /private/tmp
chmod 755 /var/run

Okay, but then it's going to run that instantly at startup. I need it to run at shutdown, not startup, so making the daemon do nothing indefinitely until it receives SIGTERM from the OS signaling shutdown/logout is what I'm aiming for. Or is there another way to do such a thing?

It's not obvious at all, and from what we have seen so far you don't appear to know exactly what you are doing, yet you're performing brain surgery on the OS. I don't care about your system, I mean you can do what ever you want, but then at least it can serve as a warning for others who might read the post.

Example: /var/run alone, from a single startup, apparently weighs in at over 600MB. Mostly on dyld_shared_cache files used for diagnostics, regardless of whether you choose to send them to Apple or not.
 

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
Okay, but then it's going to run that instantly at startup. I need it to run at shutdown, not startup, so making the daemon do nothing indefinitely until it receives SIGTERM from the OS signaling shutdown/logout is what I'm aiming for. Or is there another way to do such a thing?

It's not doing nothing indefinitely, it quits immediately. You have two plists one for the logout and one for the login right? So, at shutdown you logout script runs and at login your login script runs.


Example: /var/run alone, from a single startup, apparently weighs in at over 600MB. Mostly on dyld_shared_cache files used for diagnostics, regardless of whether you choose to send them to Apple or not.

The correct way to do this is to profile the system, but there are a lot of dependencies and old stuff in the root directory and unexpected things can happen, the kernel panic is a prime example.
 

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
You have two plists one for the logout and one for the login right? So, at shutdown you logout script runs and at login your login script runs.

Actually, this is not correct because launchd doesn't provide a key for logout or shutdown and even if it did you would need a key such as RunAtLogout or similar for the logout script. I was thinking of login/logout hooks which does exactly this. But Apple has this to say about these hooks:

Important: There are numerous reasons to avoid using login and logout scripts:
  • Login and logout scripts are a deprecated technology. In most cases, you should use launchd jobs instead, as described in“Creating Launch Daemons and Agents.”
  • Login and logout scripts are run as root, which presents a security risk.
  • Only one of each script can be installed at a time. They are intended for system administrators; application developers should not use them in released software.

https://developer.apple.com/library...up/Chapters/CustomLogin.html#//apple_ref/doc/

The other option using launchd is to make the script run forever and just let it sleep once it created the ramdisk. It would then be one script and one plist file which now should use KeepAlive -> true. The signal handler will run any time it receives a SIGTERM however, basically if you kill the script, not only on logout/shutdown. So something like this (I have not tested this).

Code:
#!/bin/bash

# SIGTERM handler
trap shutdownStuff SIGTERM

function shutdownStuff() {

}

# wrap osx_ramdisk.sh in this function
function create_ramdisk() {

    # you should probably define CACHEDIR outside of the function for clarity

}

# if volume doesn't exist, create it
if [ ! -e "$CACHEDIR" ]
then
    create_ramdisk
fi

while true
do
    sleep infinity
done
 

anh7codon

macrumors newbie
Apr 16, 2014
1
0
Actually, this is not correct because launchd doesn't provide a key for logout or shutdown and even if it did you would need a key such as RunAtLogout or similar for the logout script. I was thinking of login/logout hooks which does exactly this. But Apple has this to say about these hooks:



https://developer.apple.com/library...up/Chapters/CustomLogin.html#//apple_ref/doc/

The other option using launchd is to make the script run forever and just let it sleep once it created the ramdisk. It would then be one script and one plist file which now should use KeepAlive -> true. The signal handler will run any time it receives a SIGTERM however, basically if you kill the script, not only on logout/shutdown. So something like this (I have not tested this).

Code:
#!/bin/bash

# SIGTERM handler
trap shutdownStuff SIGTERM

function shutdownStuff() {

}

# wrap osx_ramdisk.sh in this function
function create_ramdisk() {

    # you should probably define CACHEDIR outside of the function for clarity

}

# if volume doesn't exist, create it
if [ ! -e "$CACHEDIR" ]
then
    create_ramdisk
fi

while true
do
    sleep infinity
done

Not work on Yosemite 10.10.1
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.