├── .gitignore ├── Package.swift ├── README.md ├── Sources └── Daemon.swift └── Tests ├── DaemonTests └── DaemonTests.swift └── LinuxMain.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "Daemon" 5 | ) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Swift-Daemon 2 | 3 | You can daemonize any swift process. 4 | `Daemon` can detach your swift script from shell. 5 | 6 | ```swift 7 | import Foundation 8 | import Daemon 9 | 10 | DispatchQueue(label: "foo").async { 11 | while true { 12 | print(".") 13 | sleep(1) 14 | } 15 | } 16 | 17 | Daemon.daemonize() 18 | 19 | while true { 20 | sleep(1) 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /Sources/Daemon.swift: -------------------------------------------------------------------------------- 1 | // inspired by 2 | // https://github.com/ruby/ruby/blob/trunk/process.c 3 | // https://github.com/kylef/Curassow/blob/master/Sources/Curassow/Arbiter.swift#L54 4 | #if os(Linux) 5 | import Glibc 6 | private let system_fork = Glibc.fork 7 | #else 8 | import Darwin.C 9 | @_silgen_name("fork") private func system_fork() -> Int32 10 | #endif 11 | 12 | public struct Daemon { 13 | public static func daemonize() { 14 | let devnull = open("/dev/null", O_RDWR) 15 | if devnull == -1 { 16 | fatalError("can't open /dev/null") 17 | } 18 | 19 | let pid = system_fork() 20 | if pid < 0 { 21 | fatalError("can't fork") 22 | } else if pid != 0 { 23 | exit(0) 24 | } 25 | 26 | if setsid() < 0 { 27 | fatalError("can't create session") 28 | } 29 | 30 | for descriptor in Int32(0).. () throws -> Void)] { 13 | return [ 14 | ("testExample", testExample), 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import DaemonTests 3 | 4 | XCTMain([ 5 | testCase(DaemonTests.allTests), 6 | ]) 7 | --------------------------------------------------------------------------------