Mac自启动程序管理

添加或移除启动程序,可以直接在偏好设置里面修改,首先我们需要进入系统偏好设置
这里写图片描述

然后进入用户与群组

这里写图片描述

切换至登录项,在这里我们可以添加或移除登录项

这里写图片描述

但是有时候我们发现有些自启动的软件在这里面是找不到的,这个时候我们可以通过终端程序查找。
macOS系统的启动项会以 .plist 的文件存在于以下目录中:

  • /Library/LaunchDaemons:系统启动时运行,用户不登录也会运行。
  • /Library/LaunchAgents:用户登录后运行。
  • ~/Library/LaunchAgents:用户自定义的用户启动项
  • /System/Library/LaunchDaemons:系统自带的启动项
  • /System/Library/LaunchAgents:系统自带的启动项

每个 .plist 文件中,有 3 个属性控制着是否会开机自动启动。

  • KeepAlive:决定程序是否需要一直运行,如果是 false 则需要时才启动。默认 false
  • RunAtLoad:开机时是否运行。默认 false
  • SuccessfulExit:此项为 true 时,程序正常退出时重启(即退出码为 0);为 false
    时,程序非正常退出时重启。此项设置时会隐含默认 RunAtLoad = true,因为程序需要至少运行一次才能获得退出状态。

所以其实针对这三项,不同的值有不同的表现:

  • 如果 KeepAlive = false
    • RunAtLoad = false 时:程序只有在有需要的时候运行。
    • RunAtLoad = true 时:程序在启动时会运行一次,然后等待在有需要的时候运行。
    • SuccessfulExit = true / false 时:不论 RunAtLoad
      值是什么,都会在启动时运行一次。其后根据 SuccessfulExit 值来决定是否重启。
  • 如果 KeepAlive = true :不论 RunAtLoad/SuccessfulExit
    值是什么,都会启动时运行且一直保持运行状态。

所以如果我们不希望开机自动运行,则需要:

  • 找到对应程序的 .plist 文件
  • 删除 SuccessfulExit 属性。
  • RunAtLoad / KeepAlive 均设为 <false/>

另外附上JAVA扫描开机自启动plist文件的代码供大家参考

1、MAVEN配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jianggujin</groupId>
  <artifactId>MacAutoRunScan</artifactId>
  <version>1.0.0</version>
  <name>MacAutoRunScan</name>
  <description>Mac自启动扫描</description>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- build -->
    <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
    <maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
    <java.version>1.8</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <junit.version>4.12</junit.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.googlecode.plist</groupId>
      <artifactId>dd-plist</artifactId>
      <version>1.20</version>
    </dependency>
  </dependencies>
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven-surefire-plugin.version}</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
      </plugin>
    </plugins>
  </build>
</project>

2、java代码

package com.jianggujin.macautorunscan;

/*
 * 启动类型
 */
public enum LaunchType {
   SystemLaunchDaemons("/System/Library/LaunchDaemons"), SystemLaunchAgents(
         "/System/Library/LaunchAgents"), LaunchDaemons("/Library/LaunchDaemons"), LaunchAgents(
               "/Library/LaunchAgents"), UserLaunchAgents("~/Library/LaunchAgents");
   private String path;

   private LaunchType(String path) {
      this.path = path;
   }

   public String getPath() {
      return this.path;
   }
}
package com.jianggujin.macautorunscan;

import java.io.File;

import com.dd.plist.NSDictionary;
import com.dd.plist.NSNumber;
import com.dd.plist.NSObject;
import com.dd.plist.PropertyListParser;

public class LaunchPList {
   private final File plist;
   private final LaunchType launchType;
   private NSDictionary dictionary = null;
   private Boolean keepAlive;
   private Boolean runAtLoad;
   private Boolean successfulExit;

   public LaunchPList(File plist, LaunchType launchType) {
      this.plist = plist;
      this.launchType = launchType;
   }

   public File getPlist() {
      return this.plist;
   }

   public LaunchType getLaunchType() {
      return launchType;
   }

   public Boolean getKeepAlive() {
      ensureParse();
      return keepAlive;
   }

   public Boolean getRunAtLoad() {
      ensureParse();
      return runAtLoad;
   }

   public Boolean getSuccessfulExit() {
      ensureParse();
      return successfulExit;
   }

   public String getXMLPropertyList() {
      ensureParse();
      return dictionary.toXMLPropertyList();
   }

   private Boolean getBooleanValue(String key) {
      NSObject value = null;
      if (dictionary.containsKey(key)) {
         value = dictionary.objectForKey(key);
         if (value instanceof NSNumber) {
            NSNumber number = (NSNumber) value;
            return Boolean.valueOf(number.boolValue());
         }
      }
      return null;
   }

   public boolean isAutoRun() {
      ensureParse();
      return keepAlive == Boolean.TRUE || runAtLoad == Boolean.TRUE || successfulExit != null;
   }

   private synchronized void ensureParse() {
      if (dictionary == null) {
         try {
            this.dictionary = (NSDictionary) PropertyListParser.parse(plist);
            this.keepAlive = getBooleanValue("KeepAlive");
            this.runAtLoad = getBooleanValue("RunAtLoad");
            this.successfulExit = getBooleanValue("SuccessfulExit");

         } catch (Exception e) {
            e.printStackTrace();
            dictionary = null;
            keepAlive = null;
            runAtLoad = null;
            successfulExit = null;
         }
      }
   }

   @Override
   public String toString() {
      ensureParse();
      return "LaunchPList [plist=" + plist.getAbsolutePath() + ", launchType=" + launchType + ", keepAlive=" + keepAlive
            + ", runAtLoad=" + runAtLoad + ", successfulExit=" + successfulExit + "]";
   }
}
package com.jianggujin.macautorunscan;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class LaunchScan {

   public static List<LaunchPList> scan(String name, LaunchType... launchTypes) {
      List<LaunchPList> launchPLists = new ArrayList<>();
      for (LaunchType launchType : launchTypes) {
         File root = new File(launchType.getPath());
         if (root.exists()) {
            File[] plists = root.listFiles(new FileNameFilter(name));
            if (plists != null) {
               for (File plist : plists) {
                  launchPLists.add(new LaunchPList(plist, launchType));
               }
            }
         }
      }
      return launchPLists;
   }

   static class FileNameFilter implements FilenameFilter {
      private Pattern pattern = null;;

      public FileNameFilter(String name) {
         if (name != null) {
            pattern = Pattern.compile(name);
         }
      }

      @Override
      public boolean accept(File dir, String name) {
         if (!name.endsWith(".plist")) {
            return false;
         }
         if (pattern != null) {
            return pattern.matcher(name).matches();
         }
         return true;
      }
   }
}

假如我们要扫描teamviewer的plist文件,我们可以这样写:

import java.util.List;

import org.junit.Test;

import com.jianggujin.macautorunscan.LaunchPList;
import com.jianggujin.macautorunscan.LaunchScan;
import com.jianggujin.macautorunscan.LaunchType;

public class ScanTest {
   @Test
   public void test() {
      List<LaunchPList> launchPLists = LaunchScan.scan(".*teamviewer.*", LaunchType.SystemLaunchDaemons,
            LaunchType.SystemLaunchAgents, LaunchType.LaunchDaemons, LaunchType.LaunchAgents,
            LaunchType.UserLaunchAgents);
      launchPLists.forEach(item -> {
         if (item.isAutoRun())
            System.err.println(item);
      });
   }
}

扫描参考结果如下:

LaunchPList [plist=/Library/LaunchDaemons/com.teamviewer.teamviewer_service.plist, launchType=LaunchDaemons, keepAlive=true, runAtLoad=true, successfulExit=null]
LaunchPList [plist=/Library/LaunchAgents/com.teamviewer.teamviewer.plist, launchType=LaunchAgents, keepAlive=true, runAtLoad=true, successfulExit=null]
LaunchPList [plist=/Library/LaunchAgents/com.teamviewer.teamviewer_desktop.plist, launchType=LaunchAgents, keepAlive=true, runAtLoad=true, successfulExit=null]

猜你喜欢

转载自blog.csdn.net/jianggujin/article/details/80192936