3

I have a question. When use commands line to execute a bash file I can get it to work properly. It gets the input and export it to the environment variable.

How can I make it not hang and execute the block in prompt file?

prompt file

#!/bin/bash

echo "Enter your "
read  input
echo "You said: $input"

Node.js file:

this is my node file that calls prompt file

              checkIntegration(result)
                .then(result => {
                  console.log(result, '123');
                  shell.exec('. prompt')
                })
            })

When I run it in my shell, I can enter information which is then printed:

$ . prompt
Enter your
Hello
You said: Hello

However, when I run it from node, I see the prompt but it won't accept any input:

Multiple attempts at entering text with no response

How can I make my program read user input from node's terminal?

Updated. enter image description here

my folder structure

checker.js

const {exec} = require('child_process');
var shell = require('shelljs');

function getPrompt() {
  shell.exec('. prompt');
}

getPrompt()

tokens.txt

GITLAB_URL
GITLAB_TOKEN
GITLAB_CHANNEL
GITLAB_SHOW_COMMITS_LIST
GITLAB_DEBUG
GITLAB_BRANCHES
GITLAB_SHOW_MERGE_DESCRIPTION
SLACK_TOKEN

prompt

#!/bin/bash

SOURCE="$PWD"
SETTINGS_FILE="$SOURCE/tokens.txt"
SETTINGS=`cat "$SETTINGS_FILE"`

for i in ${SETTINGS[@]}
do
echo "Enter your " $i
read  input
if [[ ! -z "$input" ]]; then
  export "$i"="$input"
fi
done
5
  • What's the value you're expecting will be read as $input in this case? Commented Jan 29, 2018 at 21:03
  • Please provide a minimal reproducible example -- the shortest possible complete code someone else can run with their own copy of node to see the problem. Commented Jan 29, 2018 at 21:13
  • My quick guess reading the API is that process.stdin is defaulting to pipe, so your child process is hanging forever waiting for Node to write something to that pipeline; see nodejs.org/api/child_process.html#child_process_options_stdio Commented Jan 29, 2018 at 21:14
  • 1
    BTW, if you're trying to modify your parent process's environment from a script, that's not going to work. A process can edit its own environment, and by extension the starting environment of programs it then invokes; it can't change the environment of the process that started it -- so your . prompt can not and will not change the environment that your Node process has, or the environment used by future scripts started by the same process. Commented Jan 29, 2018 at 21:31
  • Do note that, as I said above, the effect of the exports will be completely undone as soon as the shell invoked with . prompt exits (because, like all other environment variable changes, they are local to the process where the change is made and its children). Using . or source works when you're trying to make a change to the shell from which you invoked that command, but here, you're letting that shell exit as soon as it's done sourcing the script, utterly mooting the point. Commented Jan 29, 2018 at 21:47

2 Answers 2

2

Your read is trying to read from a pipeline from node, not from the TTY; since Node never writes to that pipe, the read hangs. To read from the TTY instead, modify your script as follows:

#!/bin/bash

# IMPORTANT: Ignore the stdin we were passed, and read from the TTY instead
exec </dev/tty

# Use a BashFAQ #1 "while read" loop

settings_file="$PWD/tokens.txt"
while read -r setting <&3; do
  printf 'Enter your %s: ' "$setting" >&2 # prompt w/ trailing newline
  IFS= read -r "$setting"                 # read directly to named variable
  export "$setting"                       # export that variable to the environment
done 3<"$settings_file"

echo "Loop is finished; printing current environment" >&2
env

Note that:

  • We're using exec </dev/tty at the top of the script to re-open the script reading directly from the TTY.

  • We're using FD 3 for the settings file to keep it distinct from stdin, so the read -r "$setting" still reads from the TTY (as reopened with the redirection above), whereas read -r setting <&3 reads from the file.

  • We're using a BashFAQ #1 while read loop to iterate over input. This is less buggy than trying to string-split a variable to get a list of names; see Why you don't read lines with for.

  • We're running env to provide output with evidence of the changes which we made to the environment -- which is important because of the below.


While this works to read input from the TTY even when your shell is launched from Node, all environment variable changes made with the above code will be lost as soon as the shell exits -- which it does before the shell.exec() call returns. If you want to change environment variables for the node process itself, you need to do that using node primitives.

You don't need bash to do this at all:

# This is node.js code to set the GITLAB_URL environment variable for the Node process
# (and any future children it may launch).
process.env['GITLAB_URL']='http://example.com/'
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for responding!!! I tried the code. It didn't save to the environment. Any idea why?
I tried to explain very clearly -- read the text in bold. (I also described the same thing in a comment on the question itself).
Got it Thanks much.
oh my, you made my day! I didn't know that you could change fd for read.
-1

I'm not familiar with node.js, but reading some documentation, it looks like the command should be child_process.exec('. prompt') This will only work if you are in the same directory as the prompt script.

Alternatively, you can try using another shell version #!/bin/sh

8 Comments

Running this in the wrong directory would cause a file-not-found failure, not a hang. And bash is a superset of POSIX sh; it supports all POSIX sh commands, including ..
@CharlesDuffy all my files are in the same directory. Its hanging when I ask for user input. There's no problem when I just run . prompt in the command line
@PakChu, are you sure you meant to direct that comment to me?
@PakChu If you run . prompt, what happens? It should just write "Enter your" and hang. Do you type anything else?
@thatotherguy hey please see updated picture above. It hangs and it wouldn't do anything. What I wanted to do is have the prompt file to ask user for series of input and export it to the environment variable. Any idea why is stuck?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.