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

Running Nightmare headlessly on Linux #224

Closed
richard5mith opened this issue Sep 16, 2015 · 113 comments
Closed

Running Nightmare headlessly on Linux #224

richard5mith opened this issue Sep 16, 2015 · 113 comments
Labels

Comments

@richard5mith
Copy link

I've taken the cnn.js example, and my only change is changing the require line from ../nightmare to nightmare, but when I run it I only get...

DEBUG=nightmare node --harmony cnn.js

nightmare queueing action "goto" +0ms    
nightmare queueing action "evaluate" +5ms

I don't ever seem to get the title of the page.

I've tried various other examples from Nightmare < 2 from around the web, and I can't get any of them to work either. Nothing ever errors, I just never seem to get any screenshot, pdf or elements pulled off the page in the output.

After 4 hours of bashing my head, I'm not sure what else to try.

@idrakimuhamad
Copy link

I tried this and got it returned properly.

nightmare queueing action "goto" +0ms
nightmare queueing action "evaluate" +1ms
Breaking News, U.S., World, Weather, Entertainment & Video News - CNN.com

But if I tried with a website that have a SLL problem, like below, it hang there for, forever.

    vo(run)(function(err, result) {
      if (err) throw err;
    });

    function *run() {
        var title = yield nightmare
        .goto('https://cas2.northport.com.my/myapp/wa/r/nmbctr')
        .evaluate(function() {
            return document.title;
        });
        console.log(title);
        yield nightmare.end();
    }

It just hang here. No error, and electron no exited.

    nightmare queueing action "goto" +0ms
    nightmare queueing action "evaluate" +1ms

@richard5mith
Copy link
Author

What's your environment for running the cnn.js script?

Entirely headless server, or in a terminal in an existing X session, or OS X etc?

@blechatellier
Copy link

I do have the same issue on a headless server. Everything runs correctly on OSX but not on my build server.

@matthewmueller
Copy link
Contributor

Yikes, major issue.

img

Seems like the electron linux binding is broken or something. Anyone have any ideas?

@matthewmueller matthewmueller changed the title No output from page parsing, but no error messages Electron broken on linux Sep 18, 2015
@richard5mith
Copy link
Author

Odd that at least you get an error message when I don't. Mine just fails silently.

My guess is that it can't get the framebuffer, which is where xvfb would normally come in. But I've tried running electron with that too and just get gtk errors.

@matthewmueller
Copy link
Contributor

Okay. I'm not exactly sure how to codify this right now (or what layer to support this in), but to get it working on the official node (docker) image, you need to do the following:

# Install dependencies
apt-get update &&\
    apt-get install -y libgtk2.0-0 libgconf-2-4 \
    libasound2 libxtst6 libxss1 libnss3 xvfb
npm install segmentio/nightmare

# Start Xvfb
Xvfb -ac -screen scrn 1280x2000x24 :9.0 &
export DISPLAY=:9.0

# Test it
apt-get install vim
vim index.js
# <paste in example>
node index.js

More info: electron/electron#228
Dockerfile: https://github.com/aheuermann/docker-electron


Could use some help on getting this bug resolved.

@matthewmueller matthewmueller changed the title Electron broken on linux Running Nightmare headlessly on Linux Sep 18, 2015
@richard5mith
Copy link
Author

That doesn't solve it for me on my environment. Still no errors, but still no title from the CNN example either.

I had previously got Gtk3::Webkit Perl module running, which also uses xvfb, and had everything installed except libxss1 already. So I know my xvfb works.

Going round in circles trying to find suggestions. I see the same as this person when running electron through xvfb-run, https://gist.github.com/AspireToCodeBetter/130877925f52c8fb2557.

And the Stack Overflow question points people here, http://stackoverflow.com/questions/32612868/running-electron-atom-shell-headlessly-on-linux-server-through-nightmare-js.

@matthewmueller
Copy link
Contributor

Oh I don't think this is it, but can you try running master? npm install segmentio/nightmare ?

I upgraded it to fix: electron-userland/electron-prebuilt#54 (comment)

@richard5mith
Copy link
Author

Hey! That did it. I can now start Xvfb on display 9 as you posted before, then I can now run the cnn example.

Looks like it was an incomplete Electron install before.

So can you modify your launch of electron process to use xvfb-run?

@matthewmueller
Copy link
Contributor

@richard5mith i'm not very familiar with xvfb, by xvfb-run do you mean the instructions i provided? or is there a simpler way?

I think it's starting a server (Xvfb -ac -screen scrn 1280x2000x24 :9.0 &), which is something I'd like to avoid. or at least have a good way to clean up after we quit.

@richard5mith
Copy link
Author

I was thinking something like this as a variation on your steps, which is how I had run Gtk Webkit .

xvfb-run --server-args="-screen 9 1280x2000x24" ./electron

That does seem to launch correctly and the renderer process starts. So I'm not sure if you can do something similar from your JS and then do the IPC with that process.

@richard5mith
Copy link
Author

Actually, this works, without having Xvfb running in the background first as per your previous steps...

DEBUG=nightmare xvfb-run --server-args="-screen 0 1024x768x24" node cnn.js

@blechatellier
Copy link

@richard5mith thanks for that, runs for me now on my build server!

@matthewmueller
Copy link
Contributor

Nice! Now just need to figure out the best way to get these dependencies on linux boxes (without using custom buildpacks or anything)

@blechatellier
Copy link

@blechatellier
Copy link

@matthewmueller I've narrowed it down to apt-get update && apt-get install -y xvfb x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps clang libdbus-1-dev libgtk2.0-dev libnotify-dev libgnome-keyring-dev libgconf2-dev libasound2-dev libcap-dev libcups2-dev libxtst-dev libxss1 libnss3-dev gcc-multilib g++-multilib

Hope that helps!

@matthewmueller
Copy link
Contributor

Thanks man, unless I'm missing something I think this should do it though: #224 (comment). Or are you talking about without node dependencies?

I think the remaining items to sort out are:

  • When do these installation procedures happen? Is this a postinstall script, a node-gyp thing, or is it something that shouldn't even be handled in this library?
  • Verify that we can run xvfb-run --server-args="-screen 0 1024x768x24" across multiple processes (in other words, running two of these spawn commands at once on the same machine)
  • Ensure that we're cleaning up the xvfb server after we execute (when the node process exits)

I plan on looking at this sometime this week or weekend, but any time offered sorting this stuff out would help accelerate this fix.

@dylanvalade
Copy link

I'm unable to fix my #223 Heroku deploy. Updated to Nightmare v2.0.6 and tried custom buildpacks but couldn't sort it out. Has anyone used xvfb on Heroku?

@matthewmueller
Copy link
Contributor

Would be good if we could get some sort of post install script going so it just worked on heroku. Sorry guys, I haven't had much time to look into this lately, but hopefully we can get this sorted out soon

@jabinb
Copy link

jabinb commented Sep 30, 2015

@matthewmueller https://github.com/Rob--W/node-xvfb might be of use for controlling the xvfb server.

@dylanvalade
Copy link

@NotSentient Jabin, Simply Wall St looks outstanding. Good find on the xvfb module.

@jney
Copy link

jney commented Oct 14, 2015

same issue there.
@dylanvalade did you find out how to make it work ?

@yoz
Copy link
Contributor

yoz commented Nov 24, 2016

@stevenmiller888 Take a look at https://github.com/captain401/heroku-buildpack-xvfb. You'll also want heroku-buildpack-apt as in the instructions.

(You might also need to include libnotify4 and libxss1 in your Aptfile - let me know if I need to update the instructions.)

@xc2f
Copy link

xc2f commented Dec 7, 2016

My website was deployed on EC2, and I tried sudo DEBUG=nightmare xvfb-run --server-args "-screen 0 1024x768x24" node app.js, but it processes the request only once
image

@GautierT
Copy link

GautierT commented Dec 7, 2016

@otaviomedeiros : Hi ! Did u manage to launch multiple long script at the same time with this config ?
I tried and when i launch 4-5 times the same script on the same xvfb display it's hang and i got some nightmare .wait() timeout.
Same if i launch multiple xvfb display and attach one script to one display.
Seems that a docker instance can't handle many xvfb display...
No error output from nightmare. Just a Error: .wait() timed out after 180000msec at last

@GautierT
Copy link

GautierT commented Dec 7, 2016

@dachow : it's seems that you killed the electron child process before the other request had time to finish. show us your code !

@xc2f
Copy link

xc2f commented Dec 8, 2016

@GautierT Hi! I have ran it with express. The basic structure of code like this:

router.get('/', function (req, res, next) {
    nightmare
        .useragent('...')
        .goto('https://www.instagram.com/')
        .click('._aj7mu._taytv._ki5uo._o0442')
        .insert('form input[type="email"]', 'xxx@gmail.com')
        .insert('form input[type="password"]', 'xxx')
        .click('form button')
        .wait('article')
        .evaluate(function () {
            // return something
        }
        .end()
        .then(function(result){
            // some handlers
            res.render('body', {
                items: items
            });
        })
        .catch(function (error) {
            console.error('Search failed:', error);
        });
}

It processes the request only once

@entrptaher
Copy link
Contributor

@dachow, that's because you are ending the instance on first run.

@jekku
Copy link
Contributor

jekku commented Dec 8, 2016

@dachow I think you can make a new instance everytime the route is called, if your resources can handle it so

@mashaalmemon
Copy link

mashaalmemon commented Dec 15, 2016

Folks following my original post on August 11, 2016 I have some more information to share. I noticed some others had similar problem that I just identified.

Going back to my post you'll see I mentioned how to get nightmare.js working on linux via the use of pm2 and Xvfb. This still applies to a linux bare metal of vm installation.

However to run nightmare in a docker a few things to keep in mind:

  • You'll need to run your node.js script and Xvfb in the docker simultaneously. pm2-docker is a good option for running multiple processes in a docker.
  • I noticed that some folks had this all working in a docker except screenshots. Or they had situations where things were working in some cases but were not. Dockers have by default 64MB shared memory (/dev/shm). Electron (chromium) needs more shared memory so you'll need to increase this. Look into docker documentation to find out more but it can be done either as part of your "docker run" command or in your .yml files. See issue Nightmare crash (Docker + Debian + xvfb) #587 .
  • Lastly electron processes that are complete stick around as Zombie processes. There are a few solutions out there. dumb-init by the folks at Yelp took me about 5 minutes to setup. On my first run the many many defunct electron processes that used to be left behind are no more.

Hopefully one or more of these points helps you folks.

@mashaalmemon
Copy link

@GautierT, no need to have multiple Xvfb displays in my experience. One Xvfb display and as many simultaneous nightmare processes as your system can handle reasonably.

@adek05
Copy link

adek05 commented Jan 1, 2017

One more thing that I encountered when trying to run using xvfb-run. Apparently, if a process executing Xvfb has pid 1, then Xvfb does not send SIGUSR1 which is what xvfb-run relies on.
More info here: https://codereview.chromium.org/1398053003/
Workaround could be as simple as running /bin/bash -c "xvfb-run <command>"

@sandstrom
Copy link

Since the ~2 weeks ago Chromium support headless mode.

With the latest Chrome Canary on Linux you can enable headless mode with the --headless command line flag. (https://bugs.chromium.org/p/chromium/issues/detail?id=546953#c148)

@matthewmueller @rosshinkley Will this change in Chromium make any difference here?

Nightmare is awesome, and a headless mode (without xvfb) would be very useful! 🥇

(here is a related issue in Electron electron/electron#228)

@dickeylth
Copy link

@sandstrom That's really cool! Looking forward to see it working in nightmare!

@Chris911
Copy link

Heroku just bumped the size of /dev/shm/ on their dyno to allow headless browser test 🎉.

https://devcenter.heroku.com/changelog-items/1085

@abcfy2
Copy link

abcfy2 commented Mar 3, 2017

I used xvfb-run, but got these error:

$ DEBUG=nightmare*,electron* xvfb-run --server-args="-screen 0 1280x2000x24" npm test -- --progress=false --single-run --watch=false

> linchang@0.0.0 test /var/lib/jenkins/workspace/customer-client-wx
> ng test --code-coverage "--progress=false" "--single-run" "--watch=false"


START:
(node:12768) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
03 03 2017 15:24:45.811:WARN [karma]: Port 9876 in use
03 03 2017 15:24:45.813:INFO [karma]: Karma v1.5.0 server started at http://0.0.0.0:9877/
03 03 2017 15:24:45.814:INFO [launcher]: Launching browser Nightmare with unlimited concurrency
03 03 2017 15:24:45.819:INFO [launcher]: Starting browser Nightmare
Fri, 03 Mar 2017 07:24:45 GMT nightmare queuing process start
Fri, 03 Mar 2017 07:24:45 GMT nightmare queueing action "goto" for http://localhost:9877/?id=7995405
Fri, 03 Mar 2017 07:24:45 GMT nightmare queueing action "wait"
Fri, 03 Mar 2017 07:24:45 GMT nightmare queueing action "evaluate"
Fri, 03 Mar 2017 07:24:45 GMT nightmare queueing action "wait"
Fri, 03 Mar 2017 07:24:45 GMT nightmare running

Fri, 03 Mar 2017 07:24:46 GMT electron:stderr Xlib:  extension "RANDR" missing on display ":99".

Fri, 03 Mar 2017 07:24:46 GMT electron:stderr Xlib:  extension "RANDR" missing on display ":99".

Fri, 03 Mar 2017 07:24:46 GMT electron:stderr [12818:0303/152446.458888:FATAL:platform_font_linux.cc(63)] Check failed: typeface. Could not find any font: Nimbus Sans L, sans
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #0 0x000001ccd51e <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #1 0x000001cb27cb <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #2 0x000003b48e3d <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #3 0x000003b48a7f <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #4 0x000003b49736 <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #5 0x000003b562f9 <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #6 0x000002a668ce <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #7 0x00000293abd3 <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #8 0x000003c13654 atom::api::WebContents::InitWithSessionAndOptions()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #9 0x000003c13dad atom::api::WebContents::WebContents()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #10 0x000003c1dd16 atom::api::WebContents::Create()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #11 0x000003c2f24f atom::api::Window::Window()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #12 0x000003c30b6c atom::api::Window::New()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #13 0x000003bece00 mate::internal::InvokeNew<>()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #14 0x000003becf90 mate::internal::Dispatcher<>::DispatchToCallback()
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #15 0x7fc91b24ceff <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #16 0x7fc91adf744b <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #17 0x7fc91adf6f09 <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr #18 0x2764fc7043a7 <unknown>
Fri, 03 Mar 2017 07:24:46 GMT electron:stderr 

Fri, 03 Mar 2017 07:24:47 GMT nightmare electron child process exited with code null: undefined

Fri, 03 Mar 2017 07:24:47 GMT nightmare electron child process not started yet, skipping kill.

03 03 2017 15:24:47.152:ERROR [launcher]: Cannot start Nightmare
	
03 03 2017 15:24:47.156:INFO [launcher]: Trying to start Nightmare again (1/2).
Fri, 03 Mar 2017 07:24:48 GMT nightmare queuing process start

@plesiecki
Copy link
Contributor

@abcfy2 Man read the log there is a clue. I'll give you a hint FATAL:platform_font_linux.cc(63)] Check failed: typeface. Could not find any font: Nimbus Sans L, sans. Peace ;)

@abcfy2
Copy link

abcfy2 commented Mar 3, 2017

It's a little strange. I find the Nimbus Sans L font exists. But after install some other fonts(I don't remember which font solved my issue, maybe apt install -y fonts-noto?), it works.

@segment-boneyard segment-boneyard locked and limited conversation to collaborators Mar 3, 2017
@matthewmueller
Copy link
Contributor

matthewmueller commented Mar 3, 2017

Hey folks, I'm going to lock this conversation since there's a ton of good information available and each comment emails approximately 300 people.

If you have an issue with getting Nightmare working on Electron please first read through the comments here. If you cannot find an answer, open a new issue. Thanks!

@matthewmueller
Copy link
Contributor

matthewmueller commented Feb 15, 2018

I want to leave an example here in case anyone comes to this thread later and finds it hard to follow. Here's a minimal way to get it running on ubuntu (via Docker):

Dockerfile

FROM node:8.3.0

RUN apt-get update

# Installing the packages needed to run Nightmare
RUN apt-get install -y \
  xvfb \
  x11-xkb-utils \
  xfonts-100dpi \
  xfonts-75dpi \
  xfonts-scalable \
  xfonts-cyrillic \
  x11-apps \
  clang \
  libdbus-1-dev \
  libgtk2.0-dev \
  libnotify-dev \
  libgnome-keyring-dev \
  libgconf2-dev \
  libasound2-dev \
  libcap-dev \
  libcups2-dev \
  libxtst-dev \
  libxss1 \
  libnss3-dev \
  gcc-multilib \
  g++-multilib

RUN npm install nightmare xvfb

index.js

const Nightmare = require('nightmare')
const Xvfb = require('xvfb')

main().catch(console.error)

// main function
async function main() {
  const close = await xvfb()
  const nightmare = Nightmare()

  const [err, title] = await poss(run(nightmare))
  if (err) {
    // cleanup properly
    await nightmare.end()
    await close()
    throw err
  }

  console.log(title)

  // shut'er down
  await nightmare.end()
  await close()
}

// run nightmare
//
// put all your nightmare commands in here
async function run(nightmare) {
  await nightmare.goto('https://google.com')
  const title = await nightmare.title()
  return title
}

// xvfb wrapper
function xvfb(options) {
  var xvfb = new Xvfb(options)

  function close() {
    return new Promise((resolve, reject) => {
      xvfb.stop(err => (err ? reject(err) : resolve()))
    })
  }

  return new Promise((resolve, reject) => {
    xvfb.start(err => (err ? reject(err) : resolve(close)))
  })
}

// try/catch helper
async function poss(promise) {
  try {
    const result = await promise
    return [null, result]
  } catch (err) {
    return [err, null]
  }
}

Makefile

build:
	@docker build -t nightmare .

run:
	@docker run -it -v $(PWD)/index.js:/index.js nightmare node index.js

run.debug:
	@docker run -it -v $(PWD)/index.js:/index.js -e DEBUG=nightmare* nightmare node index.js

Usage

make build    # build the docker container
make run      # run the container (`make run.debug` to see debug logs)

Hope this helps! 🎉

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests