Using launchd to create RAM disk cache, remove alias before shutdown?

Discussion in 'Mac Programming' started by Prodo123, Aug 24, 2014.

  1. Prodo123 macrumors 68020

    Prodo123

    Joined:
    Nov 18, 2010
    #1
    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!
     

    Attached Files:

  2. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #2
    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.
     
  3. Prodo123 thread starter macrumors 68020

    Prodo123

    Joined:
    Nov 18, 2010
    #3
    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.
     

    Attached Files:

  4. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #4
    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.

    Use the code tags (the # symbol in the post editor).
     
  5. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #5
    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.
     
  6. Prodo123 thread starter macrumors 68020

    Prodo123

    Joined:
    Nov 18, 2010
    #6
    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?
     
  7. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #7
    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
    }
    


    ----------

    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.
     
  8. Prodo123, Aug 24, 2014
    Last edited: Aug 24, 2014

    Prodo123 thread starter macrumors 68020

    Prodo123

    Joined:
    Nov 18, 2010
    #8
    Will try with RunAtLoad.

    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
    
    Obviously enough to warrant them a space on the RAM.
     
  9. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #9
    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
    


    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.
     
  10. Prodo123 thread starter macrumors 68020

    Prodo123

    Joined:
    Nov 18, 2010
    #10
    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?

    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.
     
  11. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #11
    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.


    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.
     
  12. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #12
    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
    
     
  13. anh7codon macrumors newbie

    Joined:
    Apr 16, 2014
    #13
    Not work on Yosemite 10.10.1
     

Share This Page