Kill subprocess if it becomes interactive - rust

I have the following code that runs pdflatex:
let _p2 = Command::new("pdflatex")
.arg("document.tex")
.arg("-interaction=batchmode")
.current_dir(&compile_dir)
.spawn()
.expect("There was an error")
.wait();
The problem is sometimes there are errors in the input document.tex (for example a missing closing $ for a math formula). What happens then is the terminal starts asking for user input. That is not what I want, I want the process to be killed instead (and an error sent to the user).
I've looked around the pdflatex --help but could not find any options that cancels compilation if it encounters any errors.
What would be the way to tell Command that if it encounters any interactivity, then it needs to kill the process?
Is there some way to send in a Ctrl+C cancel command via .stdin()?

The exact behavior entirely depends on the subprocess (pdflatex in this case).
By default, a subprocess launched via .spawn() will inherit the stdin file descriptor from the parent. Since the parent process has it's stdin attached to an interactive terminal, the pdflatex will inherit that and read from the same terminal.
What you can try to do is to close pdflatex's stdin before launching it, via .stdin(Stdio::null()). This will a) detach stdin for the pdflatex-process from the parent process and hence from the terminal and b) hopefully signal to the pdflatex-process that no user input is to be expected (or even possible; reading from stdin will immediately result in EOF).
It is up to pdflatex what happens, though. It is possible that pdflatex just blocks and waits forever for user input on a closed stdin; that would be considered a bug, yet it is what it is.

Related

Why we use -i or --interactive in the Node.js?

Why we use -i or --interactive in Node.js if we can easily jump into the REPL with just a simple command node ?
I have read the documentation but the documentation is a little bit confusing:
Reference Link
Opens the REPL even if stdin does not appear to be a terminal.
I understand the part Opens the REPL but didn't understand what does even if stdin does not appear to be a terminal mean ?
When executing node in a text terminal by itself, the program will provide a REPL for interactive use by a human. However, it might be the case that node is not run in a terminal, or that it was given a script to execute in a non-interactive fashion, which makes node run the given script without providing a REPL. For example, this would likely be the case for a Node.js child process which is given input and output streams between the parent process and the child process. As another example, the command below will not execute node in interactive mode:
echo "console.log('Hello');" | node
The -i option is designed to override this automatic decision, by forcing node to provide a REPL regardless of whether it has detected the presence of a text terminal. This may be particularly useful for making non-user-facing programs which streamline the REPL's inputs and outputs to another application.
Node.js itself provides an additional layer on top of input and output streams for those which are associated with a text terminal. According to the TTY module:
When Node.js detects that it is being run with a text terminal ("TTY") attached, process.stdin will, by default, be initialized as an instance of tty.ReadStream and both process.stdout and process.stderr will, by default be instances of tty.WriteStream.
If you run node and type in process.stdin.isTTY, it will output true. The following command, on the other hand, will print undefined:
echo "console.log(process.stdin.isTTY)" | node

If charger = unplugged, alert me. Command line script

I want to make a some kind of alert to let me know when the charger has disconnected (the cable doesn't fit into the socket well).
I have this to detect the status of the charger:
cat /sys/class/power_supply/ADP1/online
it returns 1 when charging and 0 when on battery.
and this to request a pop-up window:
zenity --info --text="Charger unplugged!"
I figured some kind of if statement would do the job, having to run it infinitely every second or so.
Then I remembered my days of Arduino where you could program an interrupt, that could trigger the script to run, rather than having to run it all the time.
Not sure what the best way to achieve this is. Does anybody know?
Many thanks.
You could create a service, or you can do it in a more simple and primitive way: create a script that will create a fork, redirect it's own stdout and stderr to /dev/null and execute an infinite loop that will be constantly checking your /sys/class/power_supply/ADP1/online file. When the value is 0 it will redirect the stdout and stderr to the original, in order to show the prompt. To make this an autonomous script, you would have to execute it with crontab #reboot.
I think that in the CLI it should work, but I don't know if it would work in a Graphical Desktop Interface

What are the linux signals that can be trapped in Tcl

I am working on a Tcl project where a certain procedure will run continuously. user can abort that procedure anytime using some Key-Combination. So basically, I need to trap the signal within Tcl code. So far, everything is done except one problem.
I am using Ctrl+Z i.e. SIGSUSP signal (SIGTSTP in case of Tcl) which technically does the job.
signal trap sigtstp onAbort
But, pressing Ctrl+Z immediately returns the Shell prompt, rest of the output from the program comes after that and when output comes to an end, no shell prompt returned (as it is already returned before). I need to press Enter again to get the prompt.
Following is the case I am refering to. You can see the prompt (polaris#ubuntu:~$) is returned in between output of the main program.
Also as output of pressing Ctrl+Z, it returned [40]+ Stopped, which is bit annoying. Can I avoid this ?
Can I avoid this whole problem using some other key-combination i.e. signal ? Or can I avoid this with Ctrl+Z also by tweking something ?
NOTE: I have tried using Ctrl+C. I got the exactly expected behavior with that. Unfortunately I can't use Ctrl+C as it is used for some other functionality.
Cz causes the shell to send the current foreground process a SIGSTOP(19). This signal cannot be caught or ignored and so your program will receive it and run the default handler. This is not killing the process as your question suggests you're trying to do. This only suspends it and you can bring it back into the foreground using fg on most modern shells.
Looks like you're out of luck. However, you might be able to rebind the keychord at the level of the shell. This is outside your program though and your end users don't have control over it. (Cf. https://superuser.com/questions/378018/how-can-i-do-ctrl-z-and-bg-in-one-keypress-to-make-process-continue-in-backgroun)
Also, if your program relies on user inputs for various actions (since you suggest that C-c does something else), perhaps you should make it a full fledged CUI application using curses or something?

After disown a process how can I again read the stdout of the running process

I have a c program which is running on linux. I applied some command for running the process in background after closing the terminal.
1. Pause program with `Ctrl-Z`,
2. Pull it into the background with `bg`
3. Then disown it.
Now i want to see the console output of this program which is still running.
How can I do it in linux?
If the terminal used to run the command has been closed and you are using a new one, I guess that the standard output of the background process was closed, so that you cannot do that.
A very simple way is to use screen.
Another way is to redirect output to a file when the command is run, and access the file later.

Running a node.js process in background after giving inputs to it

I have this node.js server which, once spawned, expects some input from stdin. The inputs shouldn't be given straight away: I need to wait for some event before giving them (e.g. a connection from somebody). If I give the commands and close the shell, the server shuts itself down. I would like to give the input to the server and close my shell (effectively leaving the server running).
I know that to run a process in background I need to do for example node my_server.js &, but this prevents the input from the command line. I would like to give this input AND then put it in background. Modules like forever puts it in the background automatically without letting me giving the inputs through stdin.
Moreover putting the script in background kills anyways the server when closing the shell.
Any suggestion?
Thanks
I did a quick test just using gedit in Ubuntu 12.04, and it worked.
Start your node app like so "node app.js arg1 arg2" however you want to and hit enter to start the program. Then hit CTRL-z once your program has started running. This gives you the terminal back but stops the process in the background. To let it run in the background now, simply "bg" and hit enter. This will let the process keep running now but in the background.
You can confirm you are still up with the command "ps -ef | grep node" which should show your program still running.
However, this does still leave the node process attached to the terminal window so when you close the terminal window it will close the process. But I think this will get you most of what you seem to be looking for quick and easy.
You asked for any suggestion, so here it is: make your server able to start without user interaction. The simplest way to do it is probably to create a file containing exactly the input needed by the server, then starting it like this:
node my_server.js < my_input.txt &
If the input needed depends on what the server outputs (ouch), use expect(1). If possible, subvert the whole thing and use a module like commander to get your inputs from the command line instead of stdin.

Resources