Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation about tee #26

Open
borkdude opened this issue Oct 20, 2020 · 1 comment
Open

Documentation about tee #26

borkdude opened this issue Oct 20, 2020 · 1 comment

Comments

@borkdude
Copy link
Contributor

borkdude commented Oct 20, 2020

The use case for tee is to redirect output to stdout but also to capture it in a file. We could make a built-in construct for this so you can use it to print to stdout but also capture the out stream.

(require '[babashka.process :refer [pipeline pb]]
         '[clojure.java.io :as io])

(let [[catp teep] (pipeline (pb ["cat"]) (pb ["tee" "log.txt"] {:out :inherit}))]
  ;; write to cat every 100 milliseconds 10 times
  (future
    (with-open [writer (io/writer (:in catp))]
      (loop [i 0]
        (when (< i 10)
          (binding [*out* writer]
            (println i)
            (flush))
          (Thread/sleep 100)
          (recur (inc i))))))

  @teep ;; wait for the tee process to finish
  ;; finally we print the file's content
  (println (slurp "log.txt")))

(shutdown-agents)

Also see https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/output/TeeOutputStream.html

This code is close but doesn't work yet:

(ns tee
  (:require [babashka.process :refer [process]]
            [clojure.java.io :as io])
  (:import [java.io InputStream]))

(defn tee [proc out-1 out-2]
  (let [^InputStream in (:out proc)
        ^java.lang.Process proc (:proc proc)]
    (loop [alive? (.isAlive proc) idx 0]
      (if-not alive?
        (recur (.isAlive proc) idx)
        (let [j (.available in)]
          (when (pos? j)
            (prn :read idx j)
            (let [buf (byte-array j)]
              (.read in buf idx j)
              (io/copy buf out-1)
              (io/copy buf out-2)))
          (when (.isAlive proc)
            (recur alive? (+ idx j))))))))

(def catp (process ["cat"]))

(future
  (with-open [writer (io/writer (:in catp))]
    (loop [i 0]
      (when (< i 10)
        (binding [*out* writer]
          (println i))
        (Thread/sleep 100)
        (recur (inc i))))))

(tee catp *out* *out*)

@catp

(shutdown-agents)
@duzunov
Copy link

duzunov commented Dec 10, 2021

This would be quite useful - i.e. in CI where you might have long running commands you want to interrupt instead of waiting for them to time out or error out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants