BASH: How can I successfully pipe prompt strings from built-in programs to custom script functions to then print them on the terminal?
Hi all,
The following piece of code is supposed to pipe messages from built-in programs (like apt) to a couple of custom functions, which should then (i) change the colour of the received messages to make them compliant with my script's colour theme; (ii) append the same messages to a custom log file (irrelevant for now). The trio (see: my code above) works well up until apt full-upgrade (line 29) should prompt the user with the Do you want to continue? [Y/n] message. But it's not printed on the terminal when piped through my function log_trace(), with the cursor just blinking on an empty line. But it's there, since it prints out as soon as I hit 'n' on the keyboard (to abort apt updates). I'm sure it's somehow related to one of my custom functions, but cannot figure out the reason. Is it because the "invisible" prompt line doesn't push an EOL signal to bash? Any help is highly appreciated. My system: Pop!_OS 22.04 with bash 5.1.16 on top of Linux kernel 6.5.6. Thank you! Rustam |
Most output ends with a newline, which is what your read expects when it reads lines of input. The prompt is written without a newline and then apt calls flush to print the buffer anyway. I don't think there is a way to read a variable-length line without a newline because there is no way to know you are at the end. You could read a character at a time using the -n option.
|
In the bash built-in "read" function, you could use the "-t timeout" option to accept unterminated lines. You will have to expect repeated timeouts with zero-length reads while no input is available, but always check the return code to detect EOF and break the loop. Since the incomplete line is prompting for user input, a timeout of 1 or 2 seconds should not be noticeable to the user.
|
Not sure if i have missed the point, based on the previous 2 replies, but in answer to this part:
Quote:
Code:
apt full-upgrade 2>/dev/null | log_trace "(APT)" So it is never being sent to your "log_trace" function Again, I may have misread, so apologise if I am off base |
I guess I thought prompts should go to stdout and not stderr, but "coding standards" is an oxymoron.
Anyway, if you want to read both streams do "2>&1" instead of "2>/dev/null". There will still be the issue of read expecting a newline. |
Thank you all for your suggestions! But, unfortunately, none of them works. E.g., read -t command, same as read -n, waits for a user interaction (\n) after a prompt anyway.
I also tried adding one of the IFS delimiters to the end of the string before passing it to read, to no avail. So is there maybe a command different from read to read prompts (a line at a time) from system commands like apt or find? Thanks! |
What happens if you remove the log_trace call?
I would not expect read to work as it is apt (IMHO) that is waiting for input, which you could look at expect to reply or see if this option has a way to bypass any questions? |
Quote:
Quote:
I would also point that using read -t in this situation is a bit tricky, as it will timeout and return a non-zero exit code even when it has read partial input. So just while read -t ; ... is not enough. |
All times are GMT -5. The time now is 12:17 PM. |