Skip to content

kgit2/kommand

Folders and files

NameName
Last commit message
Last commit date

Latest commit

6647946 · Jan 8, 2025
Jan 8, 2025
Jan 7, 2025
Sep 27, 2023
Dec 26, 2022
Dec 23, 2023
Jan 8, 2025
Jan 7, 2025
Aug 16, 2024
Aug 16, 2024
Jan 29, 2024
Jan 7, 2025
Jan 8, 2025
Jan 8, 2025
Jan 8, 2025
Dec 23, 2023
Dec 23, 2023
Jan 8, 2025
Jan 7, 2025

Repository files navigation

Kommand Publish Kommand Test Maven Central

ko-fi

logo

Kommand

Kotlin Native library for create sub-process and redirect their I/O.

v2.3.0

Rust is an excellent language that takes into account both performance and engineering.

In version 1.x, we use the following API to provide the function of creating child processes

  • fork of [POSIX api]
  • CreateChildProcess of [win32 api]
  • java.lang.ProcessBuilder of JVM

In version 2.x, we use the Rust standard library to provide the function of creating child processes.

  • std::process::Command of Rust
  • java.lang.ProcessBuilder of JVM

It will bring

  • More unified API
  • Easier to use API
  • Performance is still excellent
  • Easier to maintain
  • Code structure is clearer

Supported Platforms

  • x86_64-apple-darwin
  • aarch64-apple-darwin
  • x86_64-unknown-linux-gnu
  • aarch64-unknown-linux-gnu
  • x86_64-pc-windows-gnu (mingw-w64)
  • jvm

Dependent

  • Rust Standard Library 1.83.0
  • Kotlin Multiplatform 2.1.0

Usage

Dependency

build.gradle.kts:

// ……
repositories {
    mavenCentral()
}
// ……

dependencies {
    // should replace with the latest version
    implementation("com.kgit2:kommand:2.x")
}

Quick Start

Inherit Standard I/O

package com.kgit2.kommand
import com.kgit2.kommand.process.Command
import com.kgit2.kommand.process.Stdio
fun main() {
Command("ping")
.args(listOf("-c", "5", "localhost"))
.stdout(Stdio.Inherit)
.spawn()
.wait()
}

Piped I/O

package com.kgit2.kommand
import com.kgit2.kommand.process.Command
import com.kgit2.kommand.process.Stdio
fun main() {
val child = Command("ping")
.args(listOf("-c", "5", "localhost"))
.stdout(Stdio.Pipe)
.spawn()
child.bufferedStdout()?.lines()?.forEach { line ->
println(line)
}
child.wait()
}

Null I/O

package com.kgit2.kommand
import com.kgit2.kommand.process.Command
import com.kgit2.kommand.process.Stdio
fun main() {
Command("echo")
.arg("nothing")
.stdout(Stdio.Null)
.spawn()
.wait()
}

Timeout Detection

package com.kgit2.kommand
import com.kgit2.kommand.process.Command
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import kotlinx.datetime.Clock
fun main() = runBlocking(Dispatchers.Default) {
// Sleep with regular
val start = Clock.System.now()
val status = Command("sleep").arg("5").status()
println("status: $status elapsed: ${Clock.System.now() - start}")
// Sleep with timeout detection and timeout determination
val start2 = Clock.System.now()
val child = Command("sleep").arg("5").spawn()
val childJob = async(Dispatchers.IO) {
runCatching {
child.wait()
}.onFailure {
println("child result: $it")
}.getOrNull()
}
runCatching {
withTimeout(3000) {
childJob.await()
}
}.onSuccess {
println("status: $it elapsed: ${Clock.System.now() - start2}")
}.onFailure {
child.kill()
println("status: $it elapsed: ${Clock.System.now() - start2}")
}
// Sleep with timeout detection and determination that it will not timeout
val start3 = Clock.System.now()
val child2 = Command("sleep").arg("2").spawn()
val childJob2 = async(Dispatchers.IO) {
runCatching {
child2.wait()
}.onFailure {
println("child result: $it")
}.getOrNull()
}
runCatching {
withTimeout(3000) {
childJob2.await()
}
}.onSuccess {
println("status: $it elapsed: ${Clock.System.now() - start3}")
}.onFailure {
child2.kill()
println("status: $it elapsed: ${Clock.System.now() - start3}")
}
Unit
}

Full example check kommand-examples/timeout.

Dependency:

Build by yourself

1. Dependencies

  • rust toolchain - 1.83.0 (https://rustup.rs)
    • just (install with cargo install just)
  • cross-compile toolchain
    • x86_64-apple-darwin
    • aarch64-apple-darwin
    • x86_64-unknown-linux-gnu
    • aarch64-unknown-linux-gnu
    • x86_64-pc-windows-gnu (mingw-w64)
  • docker (optional)

Recommend build all platforms in macOS.

Kotlin Multiplatform gets the most complete support on macOS.

If you are using macOS, you can install the cross-compile toolchain with

just prepare

Otherwise, you need to install the cross-compile toolchain yourself.

2. Clone this repo

git clone https://github.com/kgit2/kommand.git

3. Build kommand-core

cd kommand-core
just all

4. Build kommand

./gradlew build

5. cross-platform test

Only linux support cross-platform test.

  • install docker

Install Docker Engine

  • test it
# for x86_64
just linuxX64Test
# for aarch64
just linuxArm64Test

Maintainers

@BppleMan.

@XJMiada.(Original Picture)

License

Apache2.0 © BppleMan

Credits

  • JetBrains Logo (Main) logo

Star History

Star History Chart