Issue
I have a bash script that runs perfectly well on Bash 3.2. The script contains an ampersand to run a process in the background. However, when I run it in Bash 5.x, it doesn't pass the variables correctly (I get a "SyntaxError: Unexpected end of JSON input"). When I take off the ampersand at the end (of the mgeneratejs line), it executes normally in Bash 5.
#!/bin/bash
#Works on Bash 3.2 on MacOS
#Doesn't work in bash-5.0/5.1
##!/usr/bin/env bash
NUM_ROWS_PER_RUN=5
NUM_RUNS=2
TEMPLATE_STRING='{
name: "$name"
}'
for i in $(seq 1 "$NUM_RUNS")
do
echo "Starting run ${i}"
#If you dont have it, then run "npm install -g mgeneratejs"
mgeneratejs -n "$NUM_ROWS_PER_RUN" "${TEMPLATE_STRING//[$'\r\n ']}" &
done
echo "Waiting"
wait
echo "Finished"
How can I get the process (mgeneratejs) to run in the background when using Bash 5.x?
Solution
Bash may or may not be in fault here, but be sure that the problema is in mgeneratejs
.
Taking a look mgeneratejs
's source code I found this:
if (process.stdin.isTTY) {
var str = argv._[0];
template = _.startsWith(str, '{') ? parseTemplate(str) : parseTemplate(read(str, 'utf8'));
generate();
} else {
template = '';
process.stdin.setEncoding('utf-8');
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
template += chunk;
}
});
process.stdin.on('end', function() {
template = JSON.parse(template);
generate();
});
}
If stdin
is not a TTY then mgeneratejs
assumes that stdin
is a pipe, and tries to read from it. This is wrong, they should at least check if the template has been given in the command line args.
I would't recommend that you fix mgeneratejs
, but I can recommend you to do this:
function do_run() {
echo "${TEMPLATE_STRING//[$'\r\n ']}" | mgeneratejs -n "$NUM_ROWS_PER_RUN"
}
for i in $(seq 1 "$NUM_RUNS")
do
echo "Starting run ${i}"
#If you dont have it, then run "npm install -g mgeneratejs"
do_run &
done
Answered By - JuanR