         }
     }
 
+    public func executeAsync() {
+        self.startExecution()
+    }
+
+    public func terminate() {
+        self.process.terminate()
+    }
+
+    public func waitUntilExit() {
+        self.process.waitUntilExit()
+    }
+
     public func pipe(to: String) -> ShellCommand {
         return ShellCommand(to, parentCommand: self)
     }


    @discardableResult
    public func execute() throws -> String {
        var commands = [ShellCommand]()
        var command: ShellCommand? = self
        repeat {
            commands.append(command!)
            command = command!.parentCommand
        } while command != nil

        for command in commands {
            command.process.launch()
        }

        self.process.waitUntilExit()


    private let command: [String]

    #if os(Linux)
        fileprivate let process = Task()
    #else
        fileprivate let process = Process()
    #endif

    fileprivate let parentCommand: ShellCommand?

    private init(_ command: [String], parentCommand: ShellCommand?, captureOutput: Bool) {
        self.command = command
