Last active
February 17, 2025 22:19
-
-
Save macshome/c18bd88a6b8973bd1e5bfaea738f739e to your computer and use it in GitHub Desktop.
Swift Playground to get all running processes on macOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Darwin | |
func getProcessList() { | |
// Requesting the pid of 0 from systcl will return all pids | |
var mib = [CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0] | |
var bufferSize = 0 | |
// To find the needed buffer size you call sysctl with a nil results pointer. | |
// This sets the size of the buffer needed in the bufferSize pointer. | |
if sysctl(&mib, UInt32(mib.count), nil, &bufferSize, nil, 0) < 0 { | |
perror(&errno) | |
return | |
} | |
// Determine how many kinfo_proc struts will be returned. | |
// Using stride rather than size will take alligment into account. | |
let entryCount = bufferSize / MemoryLayout<kinfo_proc>.stride | |
// Create our buffer to be filled with the list of processes and allocate it. | |
// Use defer to make sure it's deallocated when the scope ends. | |
var procList: UnsafeMutablePointer<kinfo_proc>? | |
procList = UnsafeMutablePointer.allocate(capacity: bufferSize) | |
defer { procList?.deallocate() } | |
// Now we actually perform our query to get all the processes. | |
if sysctl(&mib, UInt32(mib.count), procList, &bufferSize, nil, 0) < 0 { | |
perror(&errno) | |
return | |
} | |
// Simply step through the returned bytes and lookup the data you want. | |
// If the pid is 0 that means it's invalid and should be ignored. | |
for index in 0...entryCount { | |
guard let pid = procList?[index].kp_proc.p_pid, | |
pid != 0, | |
let comm = procList?[index].kp_proc.p_comm else { | |
continue | |
} | |
// p_comm returns the first 16 characters of the process name as a tuple of CChars. | |
// An easy way to convert it to to an array of CChars is with a Mirror. | |
// | |
// If you want the full names you can make another sysctl request for the KERN_PROCARGS2 | |
// mib for each pid. | |
let name = String(cString: Mirror(reflecting: comm).children.map(\.value) as! [CChar]) | |
print("PID: \(pid), Name: \(name)") | |
} | |
} | |
getProcessList() |
There are higher level functions for this like proc_listpids
, proc_name
than using sysctl
. They are available in proc library. I have wrapped them some time ago: libproc-swift
For those who are looking for KERN_PROCARGS2
, here it is: syscall-swift
Thanks for the comment @x13a, I was just focusing on the sysctl
API here, but as you pointed out there are easier ways to access this info.
syscall-swift
looks nice!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Swift playground code to get all the active processes using
sysctl
. Mostly for learning how to use some POSIX stuff in Swift.