2

I've created a npm module that I intend to publish, but not without testing that it works first. So I install the module I'm working with, npm install -g . and it works well on my Windows computer, but it won't run on my Linux (Debian) computer. Instead I get the following error:

15:52 $ transval
: No such file or directory

The only thing I've found so far when I compare the generated cmd and bash file on my windows computer is that whilest (when comparing to, say, 'gulp') the cmd-files are identical in structre the bash files are not. The second line, where the basedir is set differs. This the full output of the published bash file for my module:

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/node_modules/transval/bin/transval.bin.js" "$@"
  ret=$?
else 
  node  "$basedir/node_modules/transval/bin/transval.bin.js" "$@"
  ret=$?
fi
exit $ret

But if I compare the top two lines with any other file there is a significant difference! This is the top two lines from any other module, such as gulp:

#!/bin/sh
basedir=`dirname "$0"`

All other bash files get that dirname. If I change my bash file to that basedir it all of a sudden works. It is driving me mad!

EDIT: These two files are created when I run the command npm install -g . (thus installing my package globally for testing) or when I have published (i.e. npm publish), so I'm not generating these files my self.

My package.json has a bin entry which points at a file that looks like this:

#!/usr/bin/env node

var app = require('../bundle.js');
app.init(process.argv);

Anyone have any idea why it would work on Windows and not in Linux?

Maffelu
  • 2,018
  • 4
  • 24
  • 35
  • The `echo`/`sed` sequence is changing backslashes to forward slashes. Both work the same on my cygwin system. How are you generating the bash files? --- Separately, I see that you have a workaround (change the generated bash script manually). Is your question how to avoid having to make a manual change each time you update your module? – cxw Jan 10 '17 at 18:01
  • See also [this question and its answers](https://stackoverflow.com/q/59895/2877364) for ways to get `$basedir` more robustly. – cxw Jan 10 '17 at 18:03
  • Try using `${0%/*}`. I've been using it in all my scripts across Mac, Linux and Windows (cygwin and mingw). Works like a charm. – Simone Jan 10 '17 at 18:06
  • I have clarified my question a bit. The cmd and bash files are generated when I install the module via `npm install -g .` so I don't know how they are generated thus I cannot just change the basedir since it won't work for other who download my module. – Maffelu Jan 10 '17 at 18:10
  • @cxw: **bash** is version: 4.3.46(1)-release, **sed** is version 4.2.2 and **sh** is won't accept `sh --version` :) – Maffelu Jan 10 '17 at 18:43
  • Well, I think we're moving in the wrong direction. The basedir value itself doesn't matter as much as it's getting set wrong in comparison to all other 3rd party modules I have, such as gulp. – Maffelu Jan 10 '17 at 19:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132846/discussion-between-maffelu-and-cxw). – Maffelu Jan 10 '17 at 19:13

2 Answers2

1

Edit Per additional information in the OP's answer, it is indeed a line-ending problem. The problem actually is not related to $() vs. ``.

When generating on Windows, the lines end with a carriage return and a linefeed, \r\n. However, when running the generated script on Debian, only the \n is taken as the end of line. As a result, the assignment to basedir is effectively:

basedir=$(dirname "...")$'\r'
                      # ^^^^^ Carriage return!  Oops!

I think that is why the error message was ': No such file or directory': before the :, the contents of $basedir were actually printed, ending with the \r. The \r moved the cursor back to the beginning of the line, then the rest of the error message, beginning with :, overprinted the path. (That's a guess, though — I can't reproduce the exact error message on my system.)

A workaround is to put a # (space-hash) after the basedir assignment:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") #
                                         # add these ^^

That way the \r will be part of a comment and not part of basedir.


Note: see this question and its answers for other ways of getting $basedir.


Per chat, the OP is going to add the $basedir values for both options tomorrow.

For reference, here's where we are at present:

  • Per this answer, npm generates the wrapper scripts based on bin entries in the package.json.
  • npm uses the cmd-shim module to make the scripts.
  • cmd-shim was updated 2013/10/28 to use the dirname ... echo ... sed sequence so that it would work on msysgit.
  • gulp and other scripts using dirname "$0" were presumably generated with a cmd-shim predating that update.
  • The OP's Debian /bin/sh is apparently dash (currently 0.5.7-4 in debian stable).
    • for the OP, on Debian, bash is version: 4.3.46(1)-release and sed is version 4.2.2
    • I tried both basedir types on my Cygwin dash 0.5.8-3 and they both worked.

On Ubuntu, the OP has a different problem: /usr/bin/env: 'node\r': No such file or directory. That looks like a line-ending issue to me, probably different from the Debian issue.

Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81
1

Ok, found the problem. It seems to have been a problem with publishing from Windows. Once I had published from Linux (Ubuntu in this case) I could install it on both Linux and Windows computers. I'm not sure what the reason for this is, be it some npm bug or an issue with doze line breaks, but now it's working :)

I did try to publish previously from Linux, and failed, but with an old version of Node (4.something) and that didn't work but now I've upgraded to the latest version and it works well, so that might've had something to do with it.

Edit: I can now verify that publishing on a Debian machine running node 6.2.2 creates an unusable published version whereas publishing on a Ubuntu machine running node 7.4.0 works well and can be installed and run anywhere. Both machines are running npm version 4.0.5.

Maffelu
  • 2,018
  • 4
  • 24
  • 35
  • Would you be willing to help me with one more test so I can file a complete bug report? That way no one else will run into this problem in the future, and you'll be able to generate from any platform. If you're willing, please: **(1)** generate the scripts on Windows; **(2)** open the bash script in Notepad on Windows; **(3)** at the end of the `basedir=` line, add a space and a hash (`...)") #`); **(4)** try the modified script on Debian. That should work --- see my updated answer for the explanation. Please let me know if you will try it, and if so, how it works. Thanks! – cxw Jan 12 '17 at 13:39
  • I will try that on Monday and get back to your with the results :) – Maffelu Jan 14 '17 at 16:01