如何在 Heroku 上 运行 二进制文件

How to run binary on Heroku

我有一个简单的 node.js 应用程序,它 运行 在我的 OSX 开发环境中非常棒。但是当我将相同的代码推送到 Heroku 时,我在意想不到的地方返回了 undefined

行为异常的库称为 pandoc. It converts document formats. I integrating it into my node app using the wrapper package node-pdc。 Pdc 需要安装 pandoc,但它接受指定 pandoc 位置的路径,我在本地执行此操作并且效果很好。我在本地机器上全局卸载了 pandoc,以确保我指向可执行文件的正确位置。

这在本地完全符合预期:

var pdc = require('pdc');
var path = require('path');
var fs = require('fs');
var Q = require('q');

// optional, if pandoc is not in PATH
pdc.path = path.resolve(__dirname +'/pandoc/1.15.0.6/bin/pandoc');

module.exports.mdToHtml = function (input, callback) {

    //TEST
    pdc('## Emerson', 'markdown', 'html', ['--template=smashingtemplate'], function(err, result){
        console.log(result); // <h2>Emerson</h2>
    });
    ...

但是在 Heroku 上,我在日志中看到 undefined。它不会抛出任何错误。为什么它在我的笔记本电脑上可以运行,但在 Heroku 上却不能运行?

两种环境都是运行ning node v4.0.0

更新 1: 我测试了一下 pandoc 在 Heroku 上是否可用...

$ heroku run bash 

~ $ ls /app/pandoc/1.15.0.6/bin/      
pandoc
~ $ /app/pandoc/1.15.0.6/bin/pandoc --version
bash: /app/pandoc/1.15.0.6/bin/pandoc: cannot execute binary file: Exec format error
~ $ ls /app/pandoc/1.15.0.6/bin/ -lah 
total 73M
drwx------ 2 u35911 dyno 4.0K Jun  5 04:48 .
drwx------ 4 u35911 dyno 4.0K Jun  5 04:48 ..
-rwx------ 1 u35911 dyno  73M Jun  5 04:48 pandoc

二进制文件在那里。但是我不能运行他们...

更新 2

~ $ objdump -i /app/pandoc/1.15.0.6/bin/pandoc
BFD header file version (GNU Binutils for Ubuntu) 2.24
elf64-x86-64
 (header little endian, data little endian)
  i386
elf32-i386
 (header little endian, data little endian)
  i386
elf32-x86-64
 (header little endian, data little endian)
  i386
a.out-i386-linux
 (header little endian, data little endian)
  i386
pei-i386
 (header little endian, data little endian)
  i386
pei-x86-64
 (header little endian, data little endian)
  i386
elf64-l1om
 (header little endian, data little endian)
  l1om
elf64-k1om
 (header little endian, data little endian)
  k1om
elf64-little
 (header little endian, data little endian)
  i386
  l1om
  k1om
  plugin
elf64-big
 (header big endian, data big endian)
  i386
  l1om
  k1om
  plugin
elf32-little
 (header little endian, data little endian)
  i386
  l1om
  k1om
  plugin
elf32-big
 (header big endian, data big endian)
  i386
  l1om
  k1om
  plugin
pe-x86-64
 (header little endian, data little endian)
  i386
pe-i386
 (header little endian, data little endian)
  i386
plugin
 (header little endian, data little endian)
srec
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin
symbolsrec
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin
verilog
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin
tekhex
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin
binary
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin
ihex
 (header endianness unknown, data endianness unknown)
  i386
  l1om
  k1om
  plugin

               elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little 
          i386 elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 ---------- ---------- elf64-little 
          l1om ------------ ---------- ------------ ---------------- -------- ---------- elf64-l1om ---------- elf64-little 
          k1om ------------ ---------- ------------ ---------------- -------- ---------- ---------- elf64-k1om elf64-little 
        plugin ------------ ---------- ------------ ---------------- -------- ---------- ---------- ---------- elf64-little 

               elf64-big elf32-little elf32-big pe-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex 
          i386 elf64-big elf32-little elf32-big pe-x86-64 pe-i386 ------ srec symbolsrec verilog tekhex binary ihex 
          l1om elf64-big elf32-little elf32-big --------- ------- ------ srec symbolsrec verilog tekhex binary ihex 
          k1om elf64-big elf32-little elf32-big --------- ------- ------ srec symbolsrec verilog tekhex binary ihex 
        plugin elf64-big elf32-little elf32-big --------- ------- ------ srec symbolsrec verilog tekhex binary ihex 

还有...

~ $ uname -a    
Linux 7f4e1d74-8fc2-47d2-89b7-97bfc9db30dd 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:15 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

我可能没有理解正确,但看起来它们都是针对 64 架构的。

~ $ file  /app/pandoc/1.15.0.6/bin/pandoc
/app/pandoc/1.15.0.6/bin/pandoc: Mach-O 64-bit x86_64 executable

更新 3

按照@mbs1 的建议...

Creating a relocatable binary
-----------------------------

It is possible to compile pandoc such that the data files
pandoc uses are embedded in the binary.  The resulting binary
can be run from any directory and is completely self-contained.

    cabal install hsb2hs  # a required build tool
    cabal install --flags="embed_data_files" citeproc-hs
    cabal configure --flags="embed_data_files"
    cabal build

You can find the pandoc executable in `dist/build/pandoc`.  Copy this wherever
you please.

当我执行 cabal build 时,它说:

cabal: No cabal file found.
Please create a package description file <pkgname>.cabal 

解决方案

我无法使用任何需要 cabal 的解决方案。我终于使用 stack 让它工作了(一旦我弄清楚如何安装它)。

$ stack install pandoc --flag pandoc:embed-data_files

然后我将生成的 exec 文件从 vm 中复制出来并推送到 Heroku。

您是 运行 OSX 本地人。 Heroku 在 Ubuntu Linux 上运行。这些架构不是二进制兼容的。

您需要在与 Heroku 使用的完全相同的 OS 上构建 pandoc 的可重定位二进制文​​件,因此 Ubuntu Linux 系统(如果您将其安装在虚拟机中在 Mac OS X) 然后关注 this or this。基本上以下应该创建一个可重新定位的二进制文件:

stack install pandoc --flag pandoc:embed_data_files

或者,您也可以使用 Docverter,这是一种 pandoc 即服务。