Why pipes are not working on Powershell for various NodeJS CLI tools? - node.js

I am trying around the following highly used tools:
prettyjson
prettier
For example when I run the following on Powershell:
echo '{"a": 1}' | prettyjson
The terminal will just keep waiting for inputs till CTRL+C pressed and it exits with no expected output.
The workaround is to add .cmd to the command or just use cmd instead:
echo '{"a": 1}' | prettyjson.cmd
Outputs
a: 1

This seems to be a known limitation and a pull request is available:
https://github.com/npm/cmd-shim/pull/43

Related

Any way to capture Windows specific exit codes in in git-bash?

I have a scenario where a windows application that I execute in CI exits with -1073740791 eg Stack Overflow. One cmd, this can be caught obviously via %errorlevel% but on bash, at least this exit code maps to 127 in $?.
Obviously, bash on windows should not break scripting so anything above or beyond 0-255 is not fine.
Question is: Is there any special variables or mechanism directly in git-bash itself to catch this actual value ? In this case, the executable is testsuite (think off google benchhmark or google test) and exit code 127 - command not found is not helpful at all.
I had the same issue and i do not think that there is any way to do that within bash.
I decided to wrap my executable in a powershell call, append the exit code to stdout and extract it afterwards like this:
OUTPUT=$(powershell ".\"$EXECUTABLE\" $PARAMETERS 2>&1 | % ToString; echo \$LASTEXITCODE")
# Save exit code to separate variable and remove it from $OUTPUT.
EXITCODE=$(echo "$OUTPUT" | tail -n1 | tr -d '\r\n')
OUTPUT=$(sed '$d' <<< "$OUTPUT")
Some notes:
This solution does combine all stdout and stderr output into the variable $OUTPUT.
Redirecting stderr in powershell wraps the output in some error class. Calling ToString() on these returns them as normal text. This is what the | % ToString is for. Cmp. this SO Answer.
Invoking Powershell can be surprisingly slow due to Windows Defender. This can possibly be fixed by adding powershell to the list of Windows Defender exclusions.

How do I pipe input to a Node.js program that uses readline-sync?

I have a very simple Node.js program that uses readline-sync to accept input, then echo it to the console:
const readlineSync = require('readline-sync');
const input = readlineSync.prompt();
console.log(input);
It works fine as an interactive program; however, when I try to pipe input to it (in either Git Bash or PowerShell), I get a Node.js error:
PS> echo "1.2" | node .\index.js
Windows PowerShell[35552]: c:\ws\src\node_file.cc:1631: Assertion `(argc) == (5)' failed.
Adding a #!/usr/bin/env node shebang and running it as a script with echo "1.2" | .\script.js produces the same error.
Is there a configuration option or something that I'm missing that allows readline-sync to read input from a pipe? Is there something wrong with how I'm running it in the shell? Any advice would be appreciated.
It is most probably the package compatibility issue with the node version that you are using. You need to check all the dependencies whether they are compatible with the node version that you are using.
I think your program is taking 'input' in the form of 'argument' but not from 'stdin'.
when you use '|' , Input will be given to the program as 'stdin' not as 'argument'
so to convert 'stdin' coming out of '|' to 'input argument' we can use 'xargs' in linux.
try following on linux/bash to see if it works :
echo "1.2" | xargs .\script.js
Just to give a example , we can see the functionality of 'echo' command which can take 'input' only in the form of 'arguments' but not as 'stdin' :
# following command does print anything :
echo boo | echo
# but when xargs is used after | , It displays the output :
echo boo | xargs echo
boo

Base64 encoding from a website and terminal give two different results

I used following command on terminal
`echo admin:admin | base64`
It gives me following output
YWRtaW46YWRtaW4K
But when I used https://www.base64encode.org/ for the same string admin:admin it gives me following
YWRtaW46YWRtaW4=
Any reason for this?
The reason this behaviour is the new line added by the echo command. Normally the echo command add a new line at the end which leads to a different encoding. Therefore if you use it with echo -n admin:admin | base64 the difference won't occur.

Internal Variable PIPESTATUS

I am new to linux and bash scripting and i have query about this internal variable PIPESTATUS which is an array and stores the exit status of individual commands in pipe.
On command line:
$ find /home | /bin/pax -dwx ustar | /bin/gzip -c > myfile.tar.gz
$ echo ${PIPESTATUS[*]}
$ 0 0 0
working fine on command line but when I am putting this code in a bash script it is showing only one exit status. My default SHELL on command line is bash only.
Somebody please help me to understand why this behaviour is changing? And what should I do to get this work in script?
#!/bin/bash
cmdfile=/var/tmp/cmd$$
backfile=/var/tmp/backup$$
find_fun() {
find /home
}
cmd1="find_fun | /bin/pax -dwx ustar"
cmd2="/bin/gzip -c"
eval "$cmd1 | $cmd2 > $backfile.tar.gz " 2>/dev/null
echo -e " find ${PIPESTATUS[0]} \npax ${PIPESTATUS[1]} \ncompress ${PIPESTATUS[2]} > $cmdfile
The problem you are having with your script is that you aren't running the same code as you ran on the command line. You are running different code. Namely the script has the addition of eval. If you were to wrap your command line test in eval you would see that it fails in a similar manner.
The reason the eval version fails (only gives you one value in PIPESTATUS) is because you aren't executing a pipeline anymore. You are executing eval on a string that contains a pipeline. This is similar to executing /bin/bash -c 'some | pipe | line'. The thing actually being run by the current shell is a single command so it has a single exit code.
You have two choices here:
Get rid of eval (which you should do anyway as eval is generally something to avoid) and stop using a string for a command (see Bash FAQ 050 for more on why doing this is a bad idea.
Move the echo "${PIPESTATUS[#]}" into the eval and then capture (and split/parse) the resulting output. (This is clearly a worse solution in just about every way.)
Instead of ${PIPESTATUS[0]} use ${PIPESTATUS[#]}
As with any array in bash PIPESTATUS[0] contains the first command exit status. If you want to get all of them you have to use PIPESTATUS[#] which returns all the contents of the array.
I'm not sure why it worked for you when you tried it in the command line. I tested it and I didn't get the same result as you.

How can I perform some commands on Intersystem cache from shellscript?

I want to perform some commands on Intersystem cache from shell script. One solution which I know is through making a config file but the problem is I dont know how to use config file through shell script. Is there any other solution for this...
for example what I have to run on cache is
csession instancename
zn "area"
area>D ^%RI
Device:some/device/path
Next: It should take enter
This can be accomplished from a Linux shell, simply keep a log of the commands you need to perform and then put them into a script. Here's an example of logging into Cache and writing "Hello world" -- note that this also assumes you need to authenticate.
echo -e "username\npassword\nW \"Hello world\"\nH\n" | csession instance
Note that every command you would have run manually is in there and separated by "\n", this is the character that represents the "Enter" key.
It is possible (for some operating systems) to run the Cache terminal in batch mode. For example:
echo: off
wait for:Username
send: SYS<CR>
wait for:Password
send: XXX<CR>
echo: on
logfile: Somepath\myFile.log
send: ZN "AREA"
wait for:AREA>
send: D ^%RI
wait for:Device:
send: some/device/path
wait for:Next:
send: <CR>
This is documented in the Intersystems cache terminal documentation, especially the using terminal in batch mode section and the terminal scripts section.
This is a very old question .. as I came across the same thing and so with a little R&D I found a work around to this problem. Which is very cool and simple.
Let's say I have this file (can be with any extension with each command in separate line)
myScript.scr
zn "%SYS"
for e="a","b","c" { w e,! }
So passing it to cache terminal in case of UNIX is using csession with linux PIPE (|) operator
cat myScript.scr | csession {instance_name}
Eg.
cat myScript.scr | csession CACHE
output
a
b
c
Note:
• Don't separate a command in multiple lines else `csession` will through <SYNTAX> error. (See how I wrote the *for* loop)
• Extra knowledge - Intersystem Ensemble supports *Cache Terminal Batch Mode* in Windows case... While in linux there is no cterm to take the scripts..
• But linux gives you a work around to do this ;).
Hope this helps you guys!! cheers :D

Resources