I'm getting the following warning when running Aleph (which uses Netty) as a websever inside a Docker container:
WARNING: Failed to find a usable hardware address from the network interfaces; using random bytes: 75:62:7f:9b:c6:52:63:4b
I'm starting the server using:
(defn -main [& args]
(http/start-server app {:port 3000}))
And I've also tried:
(defn -main [& args]
(http/start-server app {:socket-address (java.net.InetSocketAddress. "0.0.0.0" 3000)}))
but still I get the same warning.
The warning only happens inside a docker container. I can run the server in my host without the warning. I also won't get the warning if when I run the container I use docker run --net host webserver.
The really weird thing is, despite the warning everything looks to be running fine. The correct ports are bound and the server is running correctly. Does anyone have any idea why I get this warning?
Related
A) I'm having a problem where Cider can't cider-connect-clj (or cider-connect-cljs) to an nREPL server I launch in my application code. Cursive also doesn't work. It must be a simple configuration or middleware that needs to be included. But I've been looking at this code too long. What I missing?
I have a Clojure file that looks something like this.
(ns some.namespace
(:require nrepl.server
cider.nrepl))
(nrepl.server/start-server
:port 1234
:handler
(fn [_]
(nrepl.server/default-handler cider.nrepl/cider-middleware)))
nrepl.server/start-server starts ok.
From Emacs I can connect by calling cider-connect-clj (or cider-connect-cljs). But then the REPL fails to initialize on a "sync" request.
i. Emacs console
[nREPL] Direct connection to localhost:6776 established
nrepl-send-sync-request: Sync nREPL request timed out (op clone id 1 time-stamp 2021-02-04 23:13:46.789763000)
ii. nREPL console
[WARNING] No nREPL middleware descriptor in metadata of null, see nrepl.middleware/set-descriptor!
B) I'm actually running Figwheel-Main and connecting an nREPL, for a Clojurescript connection. All within my Clojure app.
;; λ clj -A:dev -m some.namespace
:dev
{:extra-paths ["dev" "test"]
:extra-deps {org.clojure/clojure {:mvn/version "1.10.0"}
org.clojure/clojurescript {:mvn/version "1.10.520"}
com.bhauman/figwheel-main {:mvn/version "0.2.0"}
nrepl/nrepl {:mvn/version "0.8.3"}
cider/cider-nrepl {:mvn/version "0.25.8"}
cider/piggieback {:mvn/version "0.4.2"}}}
I don't think the Figwheel portion is affecting cider's attempts to connect. But I'm including it just for context.
(defn -main [& args]
;; Start Figwheel Server
(figwheel.main.api/start
{:mode :serve} "dev")
;; Start nREPL
(def server (nrepl.server/start-server
:port 1234
:handler
(fn [_]
(nrepl.server/default-handler cider.nrepl/cider-middleware))))
;; Start Figwheel REPL
(fig/cljs-repl "dev"))
It seems that you're starting the nREPL on port 1234, but then Emacs is trying to connect to port 6776. Could that be the reason?
When you run cider-connect-clj you can select the port you want connect to. Try changing the default port to 1234 and see if that helps.
In the following link
http://clojure.org/reference/repl_and_main#_launching_a_socket_server
it has detailed info about how to start socket REPL form java, but since I am using lein, so how to start from lein. If start from boot is good to run, I could also try to use boot.
To start a socket repl, you need to pass this option to the JVM
-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
In Leiningen, add this to your project.clj.
:jvm-opts ["-Dclojure.server.repl={:port 5555 :accept clojure.core.server/repl}"] ; notice that the map is not quoted.
and in Boot, export the environment variable BOOT_JVM_OPTIONS
export BOOT_JVM_OPTIONS='-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"'
Once your REPL is running, you can run telnet from a different terminal to connect to the socket REPL. REPLception!
$ telnet 127.0.0.1 5555
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
user=> (+ 1 1)
2
user=>
boot has an upcoming socket-server task. As of boot 2.7.1, a version that includes this task hasn't been released yet.
In the meantime you can use the following commands to launch Socket REPLs. To launch a Clojure process with a Socket REPL listening on port 50505 using boot, use:
boot -i "(do (require 'clojure.core.server) (clojure.core.server/start-server {:port 50505 :name :repl :accept 'clojure.core.server/repl}))" wait
Using Leiningen:
JVM_OPTS='-Dclojure.server.myrepl={:port,50505,:accept,clojure.core.server/repl}' lein repl
Using a pain Clojure jar:
java -Dclojure.server.myrepl="{:port 50505 :accept clojure.core.server/repl}" -jar ~/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar
I am running a server with the luminus web framework which uses ring/compojure and I want to be able to connect to my code with a clojure repl. I understand that there is an nrepl server which stands for network repl and that you can connect to it via: `lein repl :connect user#host:port (or some various protocol, I've tried a few things).
The following code from repl.clj is created when you auto-generate a luminus project with `lein new luminus [project-name] (actually I added the browser-repl piece necessary to attach a clojurescript repl).
(ns sophia-site.repl
(:require [cemerick.piggieback :as pig]
[weasel.repl.websocket])
(:use sophia-site.handler
ring.server.standalone
[ring.middleware file-info file]))
(defn browser-repl []
(pig/cljs-repl :repl-env
(weasel.repl.websocket/repl-env :ip "localhost" :port 9001)))
(defonce server (atom nil))
(defn get-handler []
;; #'app expands to (var app) so that when we reload our code,
;; the server is forced to re-resolve the symbol in the var
;; rather than having its own copy. When the root binding
;; changes, the server picks it up without having to restart.
(-> #'app
; Makes static assets in $PROJECT_DIR/resources/public/ available.
(wrap-file "resources")
; Content-Type, Content-Length, and Last Modified headers for files in body
(wrap-file-info)))
(defn start-server
"used for starting the server in development mode from REPL"
[& [port]]
(let [port (if port (Integer/parseInt port) 8080)]
(reset! server
(serve (get-handler)
{:port port
:init init
:auto-reload? true
:destroy destroy
:join? false}))
(println (str "You can view the site at http://some-ip:" port))))
(defn stop-server []
(.stop #server)
(reset! server nil))
I have been unsuccessful with lein repl :connect ...
What can I do to attach a clojure repl to my code on a server?
Thanks for all the help
In your project root you should run lein repl, once connected you can enter (start-server) at the repl prompt.
Your server and a browser tab will be launched and the repl prompt that you invoked (start-server) from can be used to interact with the running application.
In order to prevent a browser tab from launching you would need to add :open-browser? false to the options map passed to serve in repl.clj:
(serve (get-handler)
{:port port
:init init
:auto-reload? true
:destroy destroy
:open-browser? false
:join? false})
Running Leiningen 2.3.4 on Java 1.7.0_21 Java HotSpot(TM) 64-Bit Server VM
I am having trouble connecting to an nREPL server.
I setup a new project using lein new luminus, and then added a dependency to drawbridge ([com.cemerick/drawbridge "0.0.6"]).
I added a handler route for the repl as follows (based on https://devcenter.heroku.com/articles/debugging-clojure):
(def drawbridge-handler
(-> (cemerick.drawbridge/ring-handler)
(wrap-keyword-params)
(wrap-nested-params)
(wrap-params)
(wrap-session)))
(defn wrap-drawbridge [handler]
(fn [req]
(if (= "/repl" (:uri req))
(drawbridge-handler req)
(handler req))))
And added wrap-drawbridge to my middlewares.
I then start the server using
lein ring server-headless
The connection seems to be working well because performing a GET request on http:localhost:3000/repl yields a response: ["[\n","\n]"]
But I can't connect to the REPL:
> lein repl :connect 0.0.0.0:3000/repl
Connecting to nREPL at 0.0.0.0:3000/repl
And, after some time:
SocketException The transport's socket appears to have lost its connection to the nREPL server
clojure.tools.nrepl.transport/bencode/fn--4287/fn--4288 (transport.clj:95)
clojure.tools.nrepl.transport/bencode/fn--4287 (transport.clj:95)
clojure.tools.nrepl.transport/fn-transport/fn--4261 (transport.clj:42)
clojure.core/binding-conveyor-fn/fn--4107 (core.clj:1836)
java.util.concurrent.FutureTask$Sync.innerRun (FutureTask.java:334)
java.util.concurrent.FutureTask.run (FutureTask.java:166)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:615)
java.lang.Thread.run (Thread.java:722)
Bye for now!
Am I missing something?
Edit:
Added the following logging code to my handler:
(defn wrap-drawbridge [handler]
(fn [req]
(if (= "/repl" (:uri req))
(do (println "IN REPL ")
(drawbridge-handler req))
(handler req))))
When connecting with lein repl :connect http://localhost:3000/repl as suggested, I see the line IN REPL being printed in an infinite loop, on the servers console.
Not really a direct answer, but I've found that I was not approaching this problem the right way.
Luminus creates a project-name.repl namespace that should be used for interactive development.
I found that I could do what I wanted by adding to my project.clj
:repl-options {
:init-ns project-name.repl
:init (start-server)}
And then simply starting the server with lein repl.
Much simpler than setting up an nREPL middleware!
Have you made sure that there actually is a request entering your server (e.g. by printlining)?
However, my first guess would be that lein repl :connect behaves differently depending on whether you pass it an IP/Port pair or a fully-qualified URL. Since drawbridge seems to make nREPL accessible via HTTP I'd suggest you try:
lein repl :connect http://localhost:3000/repl
You need to add wrap-drawbridge at the first place in you middleware list.
If you do something like that
(def app (-> #'all-routes
wrap-drawbridge
...
...
...
))
It works like a charm.
[Meta notes: the following question is not answered, but the problem that the question is involved in is considered solved. Thanks to #georgek]
I am experimenting Noir web framework on a home machine running Ubuntu linux. I followed the "Getting started" part from the Noir site and got the demo server up and running. But that example was running at the testing port 8080. I wanted it to run at the default http port (port 80), so I edited the "8080" part of the clojure file my-website/src/my_website/server.clj:
(ns my-website.server
(:require [noir.server :as server]))
(server/load-views "src/my_website/views/")
(defn -main [& m]
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "80"))] ; <- I changed "8080" to "80"
(server/start port {:mode mode
:ns 'my-website})))
And tried to run the demo again, but I got the following:
$ lein run
Starting server...
2011-11-27 13:26:27.183:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2011-11-27 13:26:27.189:INFO::jetty-6.1.25
2011-11-27 13:26:27.242:WARN::failed SocketConnector#0.0.0.0:80: java.net.BindException: Permission denied
2011-11-27 13:26:27.242:WARN::failed Server#111ded2: java.net.BindException: Permission denied
Exception in thread "main" java.lang.RuntimeException: java.net.BindException: Permission denied
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Compiler.eval(Compiler.java:6476)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
...
...
I have root access to the machine, I just don't know where to start to solve this problem. Could anybody help?
What I have tried:
I tried to run lein run as su, but it didn't work either.
I stopped the Apache2 server for releasing port 80 (Is this the right way to do it?):
$ sudo /etc/init.d/apache2 stop
Still doesn't work.
I did it all over again on a macbook, it worked for port 80 ("sudo" is needed). Don't know why it doesn't work for Ubuntu.
The solution that I took
A practical solution to the problem (not an answer to the question):
I followed this web page, and used 8080 port as a service, and then configured the "httpd.conf" file of the Apache2 server to let port 8080 listen all the requests to port 80. This solution is provided by #georgek .
[I am sorry if this post is not valuable to some people, I'm new in this field. Thank you again everyone!]
An alternative solution
#ivant provides an alternative solution which also works!
Only root can use ports lower than 1024. If you say you tried running it as root or with sudo and still didn't work then most probably port 80 is already in use by some other application.
LE: This should show you which process is using the port 80
ps -eo pid,user,group,args,etime,lstart | grep `lsof -i :80 | grep LISTEN | head -1 | cut -f4 -d' '`
I would recommend running Noir as a non-root user on 8080 and using a rule to forward that domain and port to your Apache running on 80. Is there another reason you don't want to do that?
There is also privbind and authbind, which grant the privilege to bind to low ports (< 1024) to non-root apps. They are both available in ubuntu and may be a viable alternative to apache, especially while developing. To install (both) use the following:
$ sudo apt-get install privbind authbind
and check the man pages for usage instructions.
P.S. I know I'm a bit late for the party, but thought that these might still be useful.