0

I installed an app called "ShadowsocksX-NG" and then whenever I restart my computer, /Users/admin/Library/Application Support/ShadowsocksX-NG/ss-local -c ss-local-config.json will be running in the background. This is undesirable. Obviously this process is not in my Login Items. Where and how does macOS handle daemons?

  • The normal way of launching a background daemon is to put a launchd plist in /Library/LaunchDaemons/. There are a few less commonly used approaches, but I'd check that first. – Ted Wrigley Feb 8 at 14:30
  • It looks like ShadowsocksX-NG creates .plist files on ~/Library/LaunchAgents. Is it possible to disable its ability to do so - or can I disable these two files from running at startup? If I run this app, it generates those files again - so simply deleting them wouldn't help. – aeroxy Feb 9 at 12:03
  • My response is too long long for a comment, so I'll write an answer... – Ted Wrigley Feb 9 at 14:44
2

First, Shadowsocks has an active GitHub site where you can ask this question directly to the people working on the project. They're likely to know a lot more about it than anyone here.

That being said, Shadowsocks (from our discussion, above) creates these launchd plist files programmatically, so there is no easy way — short of going to GitHub and becoming a project contributor — to stop it from doing so. I assume you want ss-local to be running while Shadowsocks is running, you just don't want it to be running the rest of the time. You can do this manually through terminal using the launchctl utility. First you need to get the Label of the launchd job, so open the plist files that Shadowsocks creates in a text editor and look for something like this:

<key>Label</key>
<string>com.Shadowsocks.something.whatever</string>

The bit between the <string> tags is the launchd job label, so if you run the following command in terminal (once for each plist file):

launchctl remove com.Shadowsocks.something.whatever

It will remove the job from launchd, which shuts down whatever processes those jobs are running. I assume that Shadowsocks will restart the jobs when you launch it again, but if not, you can do that manually as well, using:

launchctl load ~/Library/LaunchAgents/<filename>.plist

You could script this in a couple of different ways, I think, but I don't know what scripting languages you're familiar with (if any), and it would be better to go to GitHub and ask for a developer solution regardless.


EDIT:

Per comments... OSX used to have to have a system for creating logout hooks through the Window Server, but that was deprecated back in 10.4, and I don't know if it still works. So instead, I'm going to tell you how to create a background script app that should do what you want.

Here's the script, follow the instructions below:

(*
  add the job labels for the plist files Shadowsocks creates to the following 
  list. This assumes that they follow the normal convention where the file name
  is the job label with '.plist' attached. If not you may need to adjust things 
  in the cleanUp() handler
*)
property labelList : {"joblabel1", "joblabel2"}
global isDirty

on run
    set isDirty to false
end run

on reopen
    display alert "Do you want to quit?" buttons {"Yes", "No"}
    if button returned of the result is "Yes" then quit
end reopen

on idle
    tell application "System Events"
        -- I'm guessing this is the process name as it appears in system events.
        -- You should double check
        if exists process "Shadowsocks-NG" then
            -- if SS is running, mark the condition as dirty
            set isDirty to true
        else
            -- if SS is not running, and isDirty is set, clean up
            if isDirty is true then
                my cleanUp()
                set isDirty to false
            end if
        end if
    end tell

    -- have the idle loop run every 15 minutes. 
    return 15*minutes
end idle

on quit
    (*
      when this app quits (which it should only do at logout, unless you quit it
      manually), clean up
    *)

    if isDirty is true then
        my cleanUp()
    end if
    continue quit
end quit

on cleanUp()
    -- remove launchd jobs, if loaded
    repeat with this_label in labelList
        try
            do shell script "launchctl remove " & this_label
        end try
    end repeat
    -- delete launch agent plist files
    tell application "System Events"
        set launchagents_folder_path to folder "LaunchAgents" of library folder of user domain
        try
            repeat with this_label in labelList
                delete (first file of launchagents_folder_path whose name is this_label & ".plist")
            end repeat
        end try
    end tell
end cleanUp
  1. Copy script into a Script Editor window, making the appropriate adjustments as noted in comments:
  2. Choose 'Save' from the file menu
  3. Change the 'File Format' pulldown to 'Application'
  4. Click the check box that says 'Stay open after run handler'
  5. Save it under whatever name you like, wherever is convenient
  6. Go to System Preferences → Security & Privacy → Privacy → Accessibility and add this app to the list of apps allowed to control your computer using accessibility.
  7. Open System Preferences and add this to your list of Login Items so it runs automatically.

Assuming that you have the launchd job names and the process name of Shadowsocks correct, this applet will sit and watch for Shadowsocks to quit, and whenever Shadowsocks quits, this app will remove the launchd jobs (shutting down the processes they are running) and delete the launch agent plist files. It will do the same thing when it quits, at logout, restart, or shutdown.

I've set the idle time to 15 minutes, which seems reasonable (on average, ss-local will only run for 7.5 minutes after you quit Shadowsocks)

Once you're sure it works the way you want, you can turn it into a proper background app. Quit the app and open its info.plist file - right-click on the app and choose "Show Package Contents"; info.plist will be down in the 'contents' folder — and add in the following key-value pair (being careful not to mess up the other key-value pairs):

<key>LSUIElement</key>
<true/>

This keeps the app from becoming visible (no dock icon, and it never becomes frontmost or takes over the menu). It can still display alerts (useful for error debugging) but that's it. You can quit it manually by double-clicking on the icon again; that's what the reopen handler is for.

| improve this answer | |
  • launchctl remove com.qiuyuzhou.shadowsocksX-NG.local and com.qiuyuzhou.shadowsocksX-NG.http will remove two processes running in the background but if I restart the mac, they will run again...While Shadowsocks is an active repo, shadowsocksX-NG the macOS client, is not. – aeroxy Feb 10 at 2:21
  • what if you write a script that deletes those plist files automatically when you computer shuts down or logs out? They won't be created until Shadowsocks runs again. – Ted Wrigley Feb 10 at 18:43
  • Sure, is there an event that would activate these scripts when the computer shuts down? – aeroxy Feb 11 at 1:48
  • I added a script solution to my answer – Ted Wrigley Feb 11 at 4:41
  • lol thx, instead I created a launchd script that runs on startup and shutdown ss-local after a 30 second timeout. This is not perfect tho. If anyone knows how to create a shutdown hook please elaborate. – aeroxy Feb 11 at 7:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .