After creating a uberjar with leiningen, and running the jar with java -jar foo-uberjar.jar
the program runs fine, and the last line of code is executed quite fast, but the program hangs for about a minute before shutting down. What is the cause of this?
(ns redditwallpaper.core
(:gen-class)
(:require [clojure.contrib.duck-streams :as duck]
[clojure.java [io :as io] [shell :as shell]]
[clojure.string :as string]
[clojure.contrib.json :as json])
(:import (java.util Random)))
(defn filename [uri]
(last (string/split uri #"/")))
(defn over_18 [x]
(:over_18 x))
(defn posts [x]
(map :data (get-in x [:data :children])))
(defn plain-image [x]
(re-find #"(.jpg|.png)$" (:url x)))
(def url "http://www.reddit.com/r/wallpaper.json")
(def wallpaperjson (json/read-json (slurp url)))
(defn copy [uri fname]
(with-open [in (io/input-stream uri)
out (io/output-stream fname)]
(.write out (duck/to-byte-array in))))
(defn randrange [n]
(.nextInt (Random.) n))
(defn randitem [xs]
(let [n (count xs)]
(nth xs (randrange n))))
(defn set-background [file]
(shell/sh "feh" "--bg-scale" file))
(defn -main [& args]
(let [posts (posts wallpaperjson)
safe (filter (complement over_18) posts)
images (filter plain-image safe)
image (:url (randitem images))
fname (filename image)]
(do
(println (format "Downloading '%s'" image))
(copy image fname)
(println (format "Setting background image to '%s'" fname))
(set-background fname)
(println "Done"))))
java -jar redditwallpaper-0.0.1-standalone.jar 2.71s user 0.34s system 4% cpu 1:03.15 total
Try adding,
(shutdown-agents)
when you are ready to exit.
I've noticed in in my experiments with bash/clojure interop that a better way might be to simply use the lein-exec plugin, for a couple of reasons.
First off, it works well for me so far.
I also ran a couple of time commands from bash to get a feeling for the difference between my original idea - which was basically to make a lein template for scripts - on the one hand, and lein-exec on the other.
On the one hand, my experiment. I hadn't made a lein template yet, but the idea was this:
(ns closcrite.core
(:require [clojure.java.shell :as shell])
(:gen-class))
(defn -main
"I don't do a whole lot."
[& args]
(let [shell-output (apply shell/sh args)]
(println (shell-output :out))
(shutdown-agents)))
The (shutdown-agents)
sexpr is simply because I ran into this problem.
Without (shutdown-agents)
:
lein compile && lein uberjar
&& time java -jar target/closcrite-0.1.0-SNAPSHOT-standalone.jar "ls" "-ahl"
Compiling closcrite.core
Compilation succeeded.
All namespaces already :aot compiled.
Created /home/j/Development/closcrite/target/closcrite-0.1.0-SNAPSHOT.jar
Including closcrite-0.1.0-SNAPSHOT.jar
Including clojure-1.4.0.jar
Created /home/j/Development/closcrite/target/closcrite-0.1.0-SNAPSHOT-standalone.jar
total 36K
drwxrwxr-x 6 j j 4.0K Aug 18 18:14 .
drwxrwxr-x 26 j j 4.0K Aug 18 17:55 ..
drwxrwxr-x 2 j j 4.0K Aug 18 17:55 doc
-rw-rw-r-- 1 j j 99 Aug 18 17:55 .gitignore
-rw-rw-r-- 1 j j 325 Aug 18 18:14 project.clj
-rw-rw-r-- 1 j j 199 Aug 18 17:55 README.md
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 src
drwxrwxr-x 4 j j 4.0K Aug 18 18:02 target
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 test
real 1m2.585s
user 0m4.188s
sys 0m0.120s
With (shutdown-agents)
:
lein compile && lein uberjar
&& time java -jar target/closcrite-0.1.0-SNAPSHOT-standalone.jar "ls" "-ahl"
Compiling closcrite.core
Compilation succeeded.
All namespaces already :aot compiled.
Created /home/j/Development/closcrite/target/closcrite-0.1.0-SNAPSHOT.jar
Including closcrite-0.1.0-SNAPSHOT.jar
Including clojure-1.4.0.jar
Created /home/j/Development/closcrite/target/closcrite-0.1.0-SNAPSHOT-standalone.jar
total 36K
drwxrwxr-x 6 j j 4.0K Aug 18 18:14 .
drwxrwxr-x 26 j j 4.0K Aug 18 17:55 ..
drwxrwxr-x 2 j j 4.0K Aug 18 17:55 doc
-rw-rw-r-- 1 j j 99 Aug 18 17:55 .gitignore
-rw-rw-r-- 1 j j 325 Aug 18 18:14 project.clj
-rw-rw-r-- 1 j j 199 Aug 18 17:55 README.md
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 src
drwxrwxr-x 4 j j 4.0K Aug 18 18:02 target
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 test
real 0m2.817s
user 0m3.796s
sys 0m0.084s
On the other hand, lein-exec:
time lein exec -e "(ns blah
(:require [clojure.java.shell :as shell]))
(print ((shell/sh \"ls\" \"-ahl\") :out))"
total 36K
drwxrwxr-x 6 j j 4.0K Aug 18 18:14 .
drwxrwxr-x 26 j j 4.0K Aug 18 17:55 ..
drwxrwxr-x 2 j j 4.0K Aug 18 17:55 doc
-rw-rw-r-- 1 j j 99 Aug 18 17:55 .gitignore
-rw-rw-r-- 1 j j 325 Aug 18 18:14 project.clj
-rw-rw-r-- 1 j j 199 Aug 18 17:55 README.md
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 src
drwxrwxr-x 4 j j 4.0K Aug 18 18:02 target
drwxrwxr-x 3 j j 4.0K Aug 18 17:55 test
real 0m1.371s
user 0m2.136s
sys 0m0.120s
Of course time
isn't the be-all end-all in profiling, but it's a nice indication of speed. For the user the inline lein-exec shell script feels almost 2x as fast as the code I used to model the execution time of a minimal leiningen shell script template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With