本文即简单介绍了如何在Swift中开发命令行工具,以及与Shell命令的交互。水文一篇,不喜勿喷。
主要是使用该工具来解析微信的性能监控组件Matrix的OOM Log。
基本模块
这里,仅简单介绍了常见的基本模块。
Process
Process类可以用来打开另外一个子进程,并监控其运行情况。
-
launchPath:指定了执行路径。如可以设置为 /usr/bin/env ,这个命令可以用于打印本机上所有的环境变量;也可以用于执行shell命令,如果你接了参数的话。本文的Demo就用它来执行输入的命令。
arguments:参数,以数组形式传递即可。
launch:调用launch函数即可启动process,用于执行命令。
waitUntilExit:一般执行Shell命令,需要等待命令返回。
terminationStatus:当前process的结束状态,正常为0.
standardOutput:standardOutput对应于终端的标准输出。standardError则是错误输出。
Pipe
Pipe这个类就是操作系统的管道,在这里用来接受子进程的输出。这里,可以用于将process的输出传递至管道指定的地方,如一个output变量,或者文件也可以。
fileHandleForReading:pipe从哪里读取内容? fileHandleForWriting:pipe将内容写到哪里?CommandLine
用于获取脚本参数而已。
print(CommandLine.argc) // 2 print(CommandLine.arguments) // ["./test.swift", "hello"]
封装Shell命令
仅执行Shell命令
这里提供了两种调用Shell命令的封装函数,个人更倾向于第二种,直接将Shell命令及参数封装成一个字符串传入即可。
@discardableResult
func runShell(_ command: String) -> Int32 {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
@discardableResult
func runShellWithArgs(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
使用如下:
runShell("pwd")
runShell("ls -l")
runShellWithArgs("pwd")
runShellWithArgs("ls", "-l")
需要Shell命令的输出内容
这里就需要使用到Pipe了。
@discardableResult
func runShellAndOutput(_ command: String) -> (Int32, String?) {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
return (task.terminationStatus, output)
}
@discardableResult
func runShellWithArgsAndOutput(_ args: String...) -> (Int32, String?) {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
return (task.terminationStatus, output)
}








