Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 08, 2016 execute bash? | ||||
---|---|---|---|---|
| ||||
Hi, I'd like to write an interactive commmand line tool for my commands, and that also support bash commands. My first thinking is 'why not just execute those bash commands with bash'? But it turns out to have some problem. When I use executeShell, I found that .bashrc is not loaded so that custom aliases like 'll' are not usable, and there is no color in the output. Then I use spawnProcess: ``` import std.process; void main() { for (int i = 0; i < 3; ++i) { // emulate the interactive loop string cmd = "ll"; wait(spwanProcess(["/bin/bash", "-i", "-c", cmd])); } } ``` with the bash option "-i", the .bashrc is loaded and the output is colored, but with each command loop, the program is stopped (equal to Ctrl-Z). I thought the subprocess may have returned some special char like Ctrl-Z, so I changed to use pipeProcess to try to catch them. But it does not work either. My question is: 1. what can I do to prevent this stop effect? 2. what is the best way to make a proxy to a bash process? |
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Puming | On Friday, 8 April 2016 at 10:08:07 UTC, Puming wrote:
> but with each command loop, the program is stopped (equal to Ctrl-Z).
Your program is stopped, right?
Odds are it is that there's terminal output for the background process, which sends your program a signal which, by default, stops it.
From man 7 stop:
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at terminal
SIGTTIN 21,21,26 Stop Terminal input for background process
SIGTTOU 22,22,27 Stop Terminal output for background process
I'd say try catching one of those signals and confirm if it is one of them and then figure out what to do next. Maybe ignoring the signal is what you want to do.
|
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 April 2016 at 13:23:10 UTC, Adam D. Ruppe wrote: > Odds are it is that there's terminal output for the background process NOT a character btw, just any output, then the OS puts you on hold so it can do its thing. To catch a signal, it is just like in C http://stackoverflow.com/a/35687472/1457000 simplest case: import core.stdc.signal; signal(SIGTTOU, SIG_IGN); // ignore the output thing and see what happens next |
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 April 2016 at 13:23:10 UTC, Adam D. Ruppe wrote: > On Friday, 8 April 2016 at 10:08:07 UTC, Puming wrote: >> but with each command loop, the program is stopped (equal to Ctrl-Z). > > Your program is stopped, right? > > Odds are it is that there's terminal output for the background process, which sends your program a signal which, by default, stops it. > > From man 7 stop: > > SIGSTOP 17,19,23 Stop Stop process > SIGTSTP 18,20,24 Stop Stop typed at terminal > SIGTTIN 21,21,26 Stop Terminal input for background process > SIGTTOU 22,22,27 Stop Terminal output for background process > Ah, that must be the case. Thanks :-) I just found that you have terminal.d in arsd repo, are you writing a repl with it? I'm hoping I might be able to use it. I'm writing a simple repl for my toy language for learning. > > > I'd say try catching one of those signals and confirm if it is one of them and then figure out what to do next. Maybe ignoring the signal is what you want to do. |
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 April 2016 at 13:25:37 UTC, Adam D. Ruppe wrote:
> On Friday, 8 April 2016 at 13:23:10 UTC, Adam D. Ruppe wrote:
>> Odds are it is that there's terminal output for the background process
>
> NOT a character btw, just any output, then the OS puts you on hold so it can do its thing.
>
> To catch a signal, it is just like in C http://stackoverflow.com/a/35687472/1457000
>
> simplest case:
>
> import core.stdc.signal;
> signal(SIGTTOU, SIG_IGN); // ignore the output thing
>
>
> and see what happens next
I tried with signal, but didn't catch SIGTTOU, it seems that spawnProcess with `bash -i -c` will signal with SIGTTIN.
When I catch SIGTTIN with:
extern(C) void sig_hand(int signal) nothrow @nogc @system {
import core.stdc.stdio: printf;
printf("signal %d catched!\n", signal);
}
I get an infinite loop of
signal 21 catched!
signal 21 catched!
signal 21 catched!
Not sure how to handle that. Maybe I can't use `bash -i`.
|
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 April 2016 at 13:25:37 UTC, Adam D. Ruppe wrote: > On Friday, 8 April 2016 at 13:23:10 UTC, Adam D. Ruppe wrote: >> Odds are it is that there's terminal output for the background process > > NOT a character btw, just any output, then the OS puts you on hold so it can do its thing. > > To catch a signal, it is just like in C http://stackoverflow.com/a/35687472/1457000 > > simplest case: > > import core.stdc.signal; > signal(SIGTTOU, SIG_IGN); // ignore the output thing > > > and see what happens next Found another problem: I can't even catch SIGINT in a simple program: import std.stdio; import std.process; import core.stdc.signal; import core.thread; import std.datetime; extern(C) void sig_hand(int signal) nothrow @nogc @system { import core.stdc.stdio: printf; printf("signal %d catched!\n", signal); } void main() { if (signal(SIGINT, &sig_hand) == SIG_ERR) { writeln("can't catch SIGINT"); } string line; write("> "); while(1) { Thread.sleep(1.seconds); } /* while ((line = readln()) != null) { writeln("you said:", line); write("> "); } */ } When using while with Thread.sleep, Ctrl+C will show signal 2 catched! then the program is gone, but its process is still found with `ps -ef`, which I have to kill manually. In the c version as shown here <http://www.thegeekstuff.com/2012/03/catch-signals-sample-c-code/>, the loop will go on and you can press multiple Ctrl-C. The D version behavior is strange. When Using while with readln, after hitting Ctrl-C, the next readln will throw exception: std.stdio.StdioException@std/stdio.d(3977): Input/output error ---------------- ??:? void std.stdio.StdioException.opCall() [0x498531] ??:? ulong std.stdio.readlnImpl(shared(core.stdc.stdio._IO_FILE)*, ref char[], dchar, std.stdio.File.Orientation) [0x498676] /usr/include/dmd/phobos/std/stdio.d:1565 ulong std.stdio.File.readln!(char).readln(ref char[], dchar) [0x486fac] /usr/include/dmd/phobos/std/stdio.d:1426 immutable(char)[] std.stdio.File.readln!(immutable(char)[]).readln(dchar) [0x486eb1] /usr/include/dmd/phobos/std/stdio.d:3385 immutable(char)[] std.stdio.readln!(immutable(char)[]).readln(dchar) [0x486e3b] source/app.d:25 _Dmain [0x48677e] ??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x48ad2a] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x48ac74] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x48ace6] ??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x48ac74] ??:? _d_run_main [0x48abe5] ??:? main [0x487b0b] ??:? __libc_start_main [0xc7628ec4] |
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Puming | On Friday, 8 April 2016 at 15:20:09 UTC, Puming wrote:
> I tried with signal, but didn't catch SIGTTOU, it seems that spawnProcess with `bash -i -c` will signal with SIGTTIN.
Oh, surely because it wants to be interactive and is thus waiting for user input from the terminal..
You might need to rig up a pseudo terminal that the bash can talk to. That's getting to be a pain though.
|
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Puming | On Friday, 8 April 2016 at 14:09:16 UTC, Puming wrote:
> I just found that you have terminal.d in arsd repo, are you
> writing a repl with it? I'm hoping I might be able to use it.
I have done it before. terminal.d has a getline function and writeln functions you could loop over. Its getline has features like tab completion, editing, etc.
|
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Puming | On Friday, 8 April 2016 at 15:31:13 UTC, Puming wrote: > The D version behavior is strange. Are you still calling bash? Cuz that is going to complicate things a lot because bash does its own signal handling too and could be intercepting it. > When Using while with readln, after hitting Ctrl-C, the next readln will throw exception: This is normal though. If a signal interrupts a read/write call, it returns an error saying it was interrupted so you can choose to abort or try again. (this way you can catch ctrl+c to cancel input) |
April 08, 2016 Re: execute bash? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Friday, 8 April 2016 at 16:07:13 UTC, Adam D. Ruppe wrote: > On Friday, 8 April 2016 at 15:20:09 UTC, Puming wrote: >> I tried with signal, but didn't catch SIGTTOU, it seems that spawnProcess with `bash -i -c` will signal with SIGTTIN. > > Oh, surely because it wants to be interactive and is thus waiting for user input from the terminal.. > > You might need to rig up a pseudo terminal that the bash can talk to. That's getting to be a pain though. You could run it through dexpect to get the effect of a pseudo terminal. https://github.com/grogancolin/dexpect |
Copyright © 1999-2021 by the D Language Foundation