添加或移除启动程序,可以直接在偏好设置里面修改,首先我们需要进入系统偏好设置
然后进入用户与群组
切换至登录项,在这里我们可以添加或移除登录项
但是有时候我们发现有些自启动的软件在这里面是找不到的,这个时候我们可以通过终端程序查找。
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]