I'm trying to create a node command line app.
What I am doing is extracting emails from a document full of information.
But when I have run the command npm link to make the script globally available, I get these errors:
/c/Users/petfle/AppData/Roaming/npm/email-extract: line 11: syntax error near unexpected token `else'
/c/Users/petfle/AppData/Roaming/npm/email-extract: line 11: `else '
My code passed linting, and I can't see any erros. I'm new to node, so it might be something simple, node specific thing that I don't see.
Here is my code:
#!/c/Program\ Files/nodejs/node
var file_stream = require('fs');
var source = process.argv[2];
var output = process.argv[3];
file_stream.readFile(source, 'utf8', function (error, data) {
var list_of_emails = extract_emails(data);
write_to_file(list_of_emails);
});
function extract_emails(data) {
return data.match(/([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)/g);
}
function write_to_file(emails) {
file_stream.writeFile(output, emails.join('\n'), 'utf8', function (error) {
console.log('Wrote ' + emails.length + ' lines to ' + output);
});
}
EDIT:
It works if I remove the shebang and run it with node myscript.js file.txt file2.txt. I'm on windows.
EDIT 2:
I'm runing this in the Git Bash. Even on windows it did run a simpler script fine with the shebang.
It works in Linux Mint 15 after removing the shebang line and invoking it through:
$ node code.js emails emailsOut
Also adding the OS-specific line #!/usr/bin/node and chmod +x code.js I can run it through
$ ./code.js emails emailsOut
Windows unfortunately doesn't work with shebang lines as such. A workaround can be found here.
Related
I am using a function from one file, in another file, and calling it there. This is causing the function to run twice at the same time when run from the command line, but not when I run it in VSCode.
Here is an example:
// fileOne
async function task() {
console.log('Hello')
}
module.exports = { task }
// fileTwo
const fileOne = require('./fileOne');
fileOne.task();
Output when ran in VSCode:
Hello
Output when ran in Command Line:
Hello
Hello
I'm not sure why this is happening... No I am not calling it in fileOne by accident because then it would also run twice in VSCode.
Thanks.
If your fileOne and fileTwo look exactly as in your problem statement, i.e.:
fileOne.js:
async function task() {
console.log('Hello')
}
module.exports = { task }
fileTwo.js:
const fileOne = require('./fileOne');
fileOne.task();
the output is 1 single 'Hello' when run in the following ways:
in Command Prompt
node fileTwo.js
in Windows PowerShell
node .\fileTwo.js
in Linux Bash Terminal
$ nodejs fileTwo.js
The same applies if you run the script having both files within 1 file (as you mention in the comments).
There were some cases where Node.js would print the output twice, but those were different scenarios.
You can try running just the fileTwo.js separately, but as already mentioned, it worked well also under a common file (e.g. your my_program_here.js in case it is just a combination of fileOne.js and fileTwo.js).
const fileOne = require('./fileOne');
This is based on the './' in different command lines.
When creating a CLI I would like to test my function. For that I'm using the module child_process.
const path = require('path');
const { execFile } = require('child_process');
describe('cli test', () => {
test('thing', () => {
const myCli = execFile(
`${path.resolve(__dirname, '..')}/cli.js`, ['--foo', 'Bar'],
(err, stdout, stderr) => {
if (err) {
console.log('err: ', err);
}
});
});
But this produces the following error:
Attempted to log "err: { Error: spawn /projects/cli/src/cli.js EACCES
at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
errno: 'EACCES',
code: 'EACCES',
Running this script directly in the terminal via the command: $ node cli.js --foo Bar works perfectly.
Now a suggestion is to chmod +x <file> that file (source). But the test should also work on CI, and on a different computer which pulls the Git repo.
Any idea?
I'd suggest using fork instead of execFile.
The child_process.fork() method is a special case of child_process.spawn() used specifically to spawn new Node.js processes.
This will allow you to execute JS files without needing them to be shell executable.
To the best of my knowledge, git actually tracks the executable bit for files. There are some things to consider though as pointed out in this article: https://medium.com/#tahteche/how-git-treats-changes-in-file-permissions-f71874ca239d
Another solution would be to not rely on the ./ execution syntax (which requires the executable bit to be turned on for the respective file) but instead to explicitly use the shell command:
const path = require('path');
const { execFile } = require('child_process');
describe('cli test', () => {
test('thing', () => {
const myCli = execFile(
`sh ${path.resolve(__dirname, '..')}/cli.js`, ['--foo', 'Bar'],
(err, stdout, stderr) => {
if (err) {
console.log('err: ', err);
}
});
});
Notice the sh prefix I added to your code, This way you thell the sh command (which should be available in all of your environments e.g. the CI) to execute the contents of the file, regardless of whether the file itself can be executed or not!
I was receiving an EACCESS -13 error from child_process.spawn when trying to run a the command line mysql command.
There was something wrong with my PATH and updating it to add /usr/local/mysql/bin/ resolved the problem.
The temporary fix is to run export PATH=$PATH:/usr/local/mysql/bin/.
The permanent fix is to:
type: sudo nano /etc/paths
Add /usr/local/mysql/bin at the end
Ctrl + X
Yes
Enter key
type hash -r # command line or close the terminal app and open it again
NOTE: I got the temporary fix from a site ... I don't know why it has a / on the end of the bin but all of the mysql executables appear to be available without it in the /etc/paths file
I am attempting to run a file in my node environment on my macbook. I keep getting the following terminal error messages:
/.../filename.js: line 2: syntax error near unexpected token `('
/.../filename.js: line 2: `const fs = require('../build/index.js');'
code:
#!/usr/bin/env node
const fs = require('../build/index.js');
The command I'm giving is:
node index.js
(I know the file names are the same but its calling a different file.)
I can't seem to figure out why it is finding the extra `.
I have tried:
Rewriting the code multiple times.
I started a new file from scratch with the same name (filename.js).
Running the code through jslint
https://www.digitalocean.com/community/questions/syntax-error-near-unexpected-token-in-node-js-for-http
I followed the exact formatting from this article: https://adrianmejia.com/blog/2016/08/12/getting-started-with-node-js-modules-require-exports-imports-npm-and-beyond/
Using double quotes instead of single quotes
Little more background, this is a project I've picked up and this is my first time trying to run it.
EDIT: Code for index.js
'use strict';
var _child_process = require('child_process');
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var l = new _logger2.default();
l.log('Starting backup');
var wd = __dirname.split('/');
var basePath = wd.slice(0, wd.length - 1).join('/');
var execPath = basePath + '/path/filename.js';
var stdout = (0, _child_process.execSync)('. ' + execPath + ' -a ' + basePath + '/something.json -b ' + basePath + '/backups');
l.log(stdout);
The issue is that the index.js calls filename.js through child_process.execSync() method, that's basically "execute this file using shell and give me its output".
Your filename.js has a shebang, and it would do intended (run using node), if not for this tiny dot in execSync() first parameter. It looks like this:
. /some/path/filename.js -a /some/path/something.json -b /some/path/backups
In sh-shells the . is a shorthand for source builtin command, that means "execute this file in shell and return its exit code". Thus, filename.js executes in shell, not in the node.
Just remove this dot (with space after it) and it will work.
Within a nodejs script I have the following code which makes the call synchronously and returns the stdout from the shell script I am calling:
var sh = require('shelljs');
... some code
var output = sh.exec('./someshellscript.sh', {silent:true}).stdout;
console.log(output);
... some more code (that shouldnt run until the script is complete)
I can also run the following script which will instead return the stderr:
var sh = require('shelljs');
... some code
var output = sh.exec('./someshellscript.sh', {silent:true}).stderr;
console.log(output);
... some more code (that shouldnt run until the script is complete)
However I want to receive both stdout and stderr in a sync call. Its probably something pretty obvious I am missing herebut I cant work it out.
I think you used to be able run the following command in previous versions but this just returns undefined now:
var sh = require('shelljs');
... some code
var output = sh.exec('./someshellscript.sh', {silent:true}).output;
console.log(output);
... some more code (that shouldnt run until the script is complete)
Relevant software versions are:
Ubuntu: 14.04.3 LTS
node: 4.4.4
npm: 2.15.1
shelljs: 0.7.0
Any help appreciated thanks.
From the README for the method exec(command [, options] [, callback])
Executes the given command synchronously, unless otherwise specified. [...], returns an object of the form { code:..., stdout:... , stderr:... }).
Therefore
const { stdout, stderr, code } = sh.exec('./someshellscript.sh', { silent: true })
Spawn in nodeJS. I have just about managed to use this to run a bash command as follows. This seems to be pretty much non-blocing and I get action on the browser screen as the command trashes through data.
ls = spawn('find',['/'] );
response.writeHead(200, { "Content-Type": "text/plain" });
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
response.write(data);
});
But I want to run a perl script with multiple arguments.
ls = spawn('blah.pl',['--argstring here', '--arg blah'] );
Perl script is just written to get arguments using getopts CPAN lib and it using CPAN expect lib to run though a pile of stuff - outputs to stdout and stderr if I have an error but I mostly care about stdout right now.
The thing is this is giving me no output. Seems to be completely blocking at least until the program finishes execution ... and it this case it doesn't at least for 10 mins.
Am I using spawn wrong?
I like the node module "carrier"
carrier = require "carrier"
childproc = require "child_process"
find = childproc.spawn "find"
find.stdout.setEncoding "utf8"
linereader = carrier.carry find.stdout
linereader.on "line", (line) -> console.log line