process input line by line with node CLI providing just an eval expression/callback to process each single line - node.js

I wonder about simple equivalent of perl -ne 'some expression' to be able to use node CLI possibly with --eval '<some expression, func/arrow>' and --require some-line-by-line-enabler. Is there any module making it possible or what can be approach to write one?
I've also found i.e. https://github.com/j-/require-cli and wonder if this may be the right way to go. I was trying it preparing some very basic module exposing forward of readline.on('line', callback) but consuming the stdin does not work just out of the box.

You can eval scripts with Node from command line:
node -e "console.log('Hello!')"

Related

How to comment all the uncommented lines in a file using puppet module

I have a sshd_config configuration file which contains commented as well as uncommented lines. I want to comment all the uncommented lines in that file using puppet. Is there any optimal/simple way to do this? Or is there a way to run bash command (maybe sed to replace) via puppet? I am not sure that using bash command is a right approach.
It would be really helpful is someone guides me with this. Thanks in advance!
Is there any optimal/simple way to do this?
There is no built-in resource type or well-known module that specifically ensures that non-blank lines of a file start with a # character.
Or is there a way to run bash command (maybe sed to replace) via puppet?
Yes, the Exec resource type. That's your best bet short of writing a custom resource type.
I am not sure that using bash command is a right approach.
In a general sense, it's not. Appropriate, specific resource types are better than Exec. But when you don't have a suitable one and can't be bothered to make one, Exec is available.
It might look like this:
# The file to work with, so that we don't have to repeat ourselves
$target_file = '/etc/ssh/sshd_config'
exec { "Comment uncommented ${target_file} lines":
# Specifying the command in array form avoids complicated quoting or any
# risk of Puppet word-splitting the command incorrectly
command => ['sed', '-i', '-e', '/^[[:space:]]*[^#]/ s/^/# /', $target_file],
# If we didn't specify a search path then we would need to use fully-qualified
# command names in 'command' above and 'onlyif' below
path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'],
# The file needs to be modified only if it contains any non-blank, uncommented
# lines. Testing that via an 'onlyif' ensures that Puppet will not
# run 'sed' or (more importantly) report the file changed when it does
# not initially contain any lines that need to be commented
onlyif => [['grep', '-q', '^[[:space:]]*[^#]', $target_file]],
# This is the default provider for any target node where the rest of this
# resource would work anyway. Specifying it explicitly will lead to a more
# informative diagnostic if there is an attempt to apply this resource to
# a system to which it is unsuited.
provider => 'posix',
}
That does not rely on bash or any other shell to run the commands, but it does rely on sed and grep being available in one of the specified directories. In fact, it relies specifically on GNU sed or one that supports an -i option with the same semantics. Notably, that does not include BSD-style sed, such as you will find on macOS.

Prevent script running with same arguments twice

We are looking into building a logcheck script that will tail a given log file and email when the given arguments are found. I am having trouble accurately determining if another version of this script is running with at least one of the same arguments against the same file. Script can take the following:
logcheck -i <filename(s)> <searchCriterion> <optionalEmailAddresses>
I have tried to use ps aux with a series of grep, sed, and cut, but it always ends up being more code than the script itself and seldom works very efficiently. Is there an efficient way to tell if another version of this script is running with the same filename and search criteria? A few examples of input:
EX1 .\logcheck -i file1,file2,file3 "foo string 0123" email#address.com
EX2 .\logcheck -s file1 Hello,World,Foo
EX3 .\logcheck -i file3 foo email#address1.com,email#address2.com
In this case 3 should not run because 1 is already running with parameters file3 and foo.
There are many solutions for your problem, I would recommend creating a lock file, with the following format:
arg1Ex1 PID#(Ex1)
arg2Ex1 PID#(Ex1)
arg3Ex1 PID#(Ex1)
arg4Ex1 PID#(Ex1)
arg1Ex2 PID#(Ex2)
arg2Ex2 PID#(Ex2)
arg3Ex2 PID#(Ex2)
arg4Ex2 PID#(Ex2)
when your script starts:
It will search in the file for all the arguments it has received (awk command or grep)
If one of the arguments is present in the list, fetch the process PID (awk 'print $2' for example) to check if it is still running (ps) (double check for concurrency and in case of process ended abnormally previously garbage might remain inside the file)
If the PID is still there, the script will not run
Else append the arguments to the lock file with the current process PID and run the script.
At the end, of the execution you remove the lines that contains the arguments that have been used by the script, or remove all lines with its PID.

Cannot enable multiple harmony flags nodejs

I wrote a NodeJs script using ES6 features (default parameters and destructuring), so I put the following shebang:
#!/bin/node --harmony_destructuring --harmony_default_parameters
But then node tells me:
/bin/node: bad option: --harmony_destructuring --harmony_default_parameters
Both of these options are listed in node --v8-options | grep "in progress" so they should be both valid, but maybe my syntax is incorrect.
I tried different syntaxs:
/bin/node: bad option: --harmony_destructuring=true --harmony_default_parameters=true
/bin/node: bad option: --harmony_destructuring true --harmony_default_parameters true
With no luck.
Although I found this fascinating answer for python, I don't have something that clever for javascript available. I think you are going to need 2 separate files: 1 small wrapper script to force the arguments you need to node and a separate file for your javascript.
#!/bin/sh
exec node --harmony_destructuring=true --harmony_default_parameters=true my-script.js "$#"

How to preserve quotes in a bash parameter?

I have a bash script (Mac OS X) that in turns calls a Node.js command line application.
I normally call the Node.js app like this:
node mynodeapp events:"Open project"
Which node has no problem parsing as one parameter, in spite of the space between "Open" and "project".
I call my bash script like this:
. mybashscript.sh 2014-03-20 "Open project"
Inside the bash script I have:
EVENTSQUOTES=\"$2\"
echo node mixpanel-extract date:$1 events:$EVENTSQUOTES
node mixpanel-extract date:$1 events:$EVENTSQUOTES
Running the script produces:
node mixpanel-extract date:2014-03-20 events:"Open project"
Parameters: { date: '2014-03-20',
events: [ '"Open' ] }
So although the echo output line looks fine, the Parameters: output from my Node.js app tells me that bash splits the parameter in two. I've also tried wrapping it in more quotes e.g. EVENTSQUOTES='\"$2\"' but it makes no difference.
You need to use quote while calling also:
node mixpanel-extract date:"$1" events:"$EVENTSQUOTES"
echo node mixpanel-extract "date:$1" "events:$2"
node mixpanel-extract "date:$1" "events:$2"
You need to quote the variable when you use it as well, otherwise word splitting will occur.

Enable Harmony ES6 features in V8 at runtime in a module?

Node v0.10.20 provides many options pertaining to harmony,
--harmony_typeof (enable harmony semantics for typeof)
--harmony_scoping (enable harmony block scoping)
--harmony_modules (enable harmony modules (implies block scoping)
--harmony_proxies (enable harmony proxies)
--harmony_collections (enable harmony collections (sets, maps, and weak maps))
--harmony (enable all harmony features (except typeof))
I understand that these are not production-ready features and that they're under development, but many of them are good enough.
Is there a way to enable them at runtime?
"use strict";
"use harmony collections";
Something like the above. Even if it's not just module-level enabling of those features, it'd be nice to ensure they were enabled inside the module rather than assume they were enabled.
No, you can't. In fact, some things might potentially go horribly wrong within V8 internals if you tried to sneak in multiple different settings of these flags within the same V8 instance (disclosure: I implemented most of these flags).
There is no way to do this, the interpreter reads the content of the modules then validate them and then evaluate them. If you will use some ES6 specific syntax then the validation will fail and the code will not be evaluated.
You only could isolate the ES6 syntax files and run them as child processes (with the necessary options), but I guess this is not the way you want to do this.
The previous answer isn't such a bad idea, for a module, (isolating the ES6 files in an exec/child process), if you can handle the idea of it being run in a child process.
The best seeming answer is to, if you're a module, document that you require these features and test for them at run time and bail with a helpful error. I haven't myself exactly figured out how to test for this nicely (give me a break, I've been using node for 3 days)
If you're writing an app, the answer is slightly different. In my case, the app I am writing will likely make use of these features - and due to the limitation of only being able to use a single parameter in the shebang line, not being able to change the JS version during runtime (which, of course, as explained above, makes complete sense), and not wanting to exec a child process (my server is already multithreaded) - I have been forced to write a script to run my node server so that my users don't have to figure out the proper node commmand line to run my app (ugly) and if I ever want to use more than --harmony and "use strict"; I can do it with the script as it is just a shell script that calls node and my app..
It is recommended to use #!/usr/bin/env node as the shebang (which will find node for you, wherever it is installed to) however, you can only use one parameter in the shebang so this won't work with --harmony (or any other parameter)
Of course - you can always run node --harmony --use_strict --blah_blah yourScript.js, but if you need certain options you'll have to type it every time, hence using a shell script is advised (by me!). I suppose you could include this (or such a) script with your module and recommend it's use in executing the app that uses your module.
This is a similar implementation to the shell script that I am using for my server, it will find node and run your script with whichever parameters you require:
#!/bin/bash
if [ "$myScript" == "" ]; then
myScript="./src/myNodeServer.js"
fi
if [ "$myNodeParameters" == "" ]; then
myNodeParameters="--harmony --use_strict"
fi
if [ "$myNode" = "" ]; then
myNode=`which node`
fi
if [ "$myNode" = "" ]; then
echo node was not found! this app requires nodeJS to be installed in order to run.
echo if you have nodeJS installed but is not found, please make sure the 'which'
echo command is available. alternatively, you can forcibly specify the location of
echo node with the $myNode environment variable, or editing this file.
else
echo Yay! node binary was found at $myNode
fi
if [ "$1" = "start" ]; then
echo you asked to start..
echo calling $myNode $myParameters $myScript $2
$myNode $myParameters $myScript $2
exit
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
echo you asked for help..
echo usage:
echo $0 start [script.js] [parameters for script]
echo parameters for node and node location can be
echo set with the \$myParameters and \$myNode env
echo variables (or edit the top of this file).
exit
else
echo no valid command specified - use $0 --help to see help.
fi
It's worth noting, if you ONLY want to use harmony and strict, while you can't specify both in a shebang, you can hardcode the location of node and use the "use strict"; alias:
#!/usr/bin/node --harmony
"use strict";

Resources