为什么当前进度的``stdin''在popen()```popen'''命令的行为''?
根据popen
的手册,该手册说[强调矿山]:
popen()函数通过创建管道,分叉和调用外壳来打开一个过程。由于管道是单向的,因此 类型参数可以仅指定阅读或写作,而不是两者兼而有之。所得流相应地读取或仅写入 。
。
根据上述语句,无法将popen
返回的文件流编写和读取。因此,我认为当前过程的stdin
不会影响shell命令的行为,而 。
但这确实是我在下面运行程序时的期望。
这是代码段代码:
//filename pipe_cmd.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int ret = 0;
FILE* file = popen("ssh -t [email protected] bash -c 'top' ", "r");
int fd = fileno(file);
char buffer[1024*100];
if(NULL != file)
{
while (true) {
memset(buffer, '\0', sizeof(buffer));
int ret_read = read(fd, buffer, sizeof(buffer));
if (ret_read > 0) {
printf("%s", buffer);
} else if (0 == ret_read) {
ret = 0;
break;
} else {
ret = -1;
break;
}
}
}
return ret;
}
代码段是由gcc pipe_cmd.c -o Pipe_cmd
编辑的。
当程序名为Pipe_cmd
正在运行时,我可以看到有关远程计算机上的所有信息,这是预期的。
但是,当我点击h
键时,我可以在我的 本地终端 上看到此类帮助消息,这确实是 。我的期望 。这是我看到的:
Help for Interactive Commands - procps-ng version 3.3.9
Window 1:Def: Cumulative mode Off. System: Delay 0.1 secs; Secure mode Off.
Z,B,E,e Global: 'Z' colors; 'B' bold; 'E'/'e' summary/task memory scale
l,t,m Toggle Summary: 'l' load avg; 't' task/cpu stats; 'm' memory info
0,1,2,3,I Toggle: '0' zeros; '1/2/3' cpus or numa node views; 'I' Irix mode
f,F,X Fields: 'f'/'F' add/remove/order/sort; 'X' increase fixed-width
L,&,<,> . Locate: 'L'/'&' find/again; Move sort column: '<'/'>' left/right
R,H,V,J . Toggle: 'R' Sort; 'H' Threads; 'V' Forest view; 'J' Num justify
c,i,S,j . Toggle: 'c' Cmd name/line; 'i' Idle; 'S' Time; 'j' Str justify
x,y . Toggle highlights: 'x' sort field; 'y' running tasks
z,b . Toggle: 'z' color/mono; 'b' bold/reverse (only if 'x' or 'y')
u,U,o,O . Filter by: 'u'/'U' effective/any user; 'o'/'O' other criteria
n,#,^O . Set: 'n'/'#' max tasks displayed; Show: Ctrl+'O' other filter(s)
C,... . Toggle scroll coordinates msg for: up,down,left,right,home,end
k,r Manipulate tasks: 'k' kill; 'r' renice
d or s Set update interval
W,Y Write configuration file 'W'; Inspect other output 'Y'
q Quit
( commands shown with '.' require a visible task display window )
Press 'h' or '?' for help with Windows,
令人惊讶!上述行为看起来像top
命令在我的本地bash中直接调用,但它确实是由popen
命名的。
我现在真的很困惑。有人可以阐明这件事吗?
Note :
代码shippet中的IP地址(IE 192.168.1.51
)是我本地计算机的IP。但是我认为这不是该程序应该以这种方式工作的原因。
我现在将尝试在另一台计算机上运行此程序。
更新了 :
当该程序在另一台计算机上运行的IP地址不同而没有修改上述代码段的其他计算机时,某些现象。
如何解决这个问题?我不希望当前过程的stdin
影响壳命令的行为。我知道的一种方法是使用管道
&amp; fork
并关闭stdin
。使用Popen
实现此目标的更好方法?
As per the manual of popen
, which says that[emphasis mine]:
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
As per the statements above, there is no way to both write and read to the file stream returned by popen
. So I take it for granted that the stdin
of current process would not influence the behaviour of the shell command which is passed as parameter for popen()
.
But it's really out of my expectation when running the program below.
Here is the code snippet code:
//filename pipe_cmd.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int ret = 0;
FILE* file = popen("ssh -t [email protected] bash -c 'top' ", "r");
int fd = fileno(file);
char buffer[1024*100];
if(NULL != file)
{
while (true) {
memset(buffer, '\0', sizeof(buffer));
int ret_read = read(fd, buffer, sizeof(buffer));
if (ret_read > 0) {
printf("%s", buffer);
} else if (0 == ret_read) {
ret = 0;
break;
} else {
ret = -1;
break;
}
}
}
return ret;
}
The code snippet is compiled by gcc pipe_cmd.c -o pipe_cmd
.
When program named pipe_cmd
is running, I can see the all the information about the processes on the remote computer, which is as expected.
But when I hit h
key, I can see such help message on my local terminal, which is really out of my expectation. Here is what I see:
Help for Interactive Commands - procps-ng version 3.3.9
Window 1:Def: Cumulative mode Off. System: Delay 0.1 secs; Secure mode Off.
Z,B,E,e Global: 'Z' colors; 'B' bold; 'E'/'e' summary/task memory scale
l,t,m Toggle Summary: 'l' load avg; 't' task/cpu stats; 'm' memory info
0,1,2,3,I Toggle: '0' zeros; '1/2/3' cpus or numa node views; 'I' Irix mode
f,F,X Fields: 'f'/'F' add/remove/order/sort; 'X' increase fixed-width
L,&,<,> . Locate: 'L'/'&' find/again; Move sort column: '<'/'>' left/right
R,H,V,J . Toggle: 'R' Sort; 'H' Threads; 'V' Forest view; 'J' Num justify
c,i,S,j . Toggle: 'c' Cmd name/line; 'i' Idle; 'S' Time; 'j' Str justify
x,y . Toggle highlights: 'x' sort field; 'y' running tasks
z,b . Toggle: 'z' color/mono; 'b' bold/reverse (only if 'x' or 'y')
u,U,o,O . Filter by: 'u'/'U' effective/any user; 'o'/'O' other criteria
n,#,^O . Set: 'n'/'#' max tasks displayed; Show: Ctrl+'O' other filter(s)
C,... . Toggle scroll coordinates msg for: up,down,left,right,home,end
k,r Manipulate tasks: 'k' kill; 'r' renice
d or s Set update interval
W,Y Write configuration file 'W'; Inspect other output 'Y'
q Quit
( commands shown with '.' require a visible task display window )
Press 'h' or '?' for help with Windows,
What a surprise! The aforementioned behaviour looks like the top
command is directly called in my local bash, but it's really called by popen
.
I am really confused now. Could somebody shed some light on this matter?
Note:
The IP address(i.e. 192.168.1.51
) in the code snippet is my local computer's IP. But I don't think it's the reason why the program should work in this way.
I will try to run this program on another computer right now.
UPDATED:
Some phenomena when this program runs on another computer whose IP address is different without any modification for the aforementioned code snippet.
How to solve this problem? I don't want the stdin
of current process influence the behaviour of the shell command. One method that I know is to use pipe
& fork
and close the stdin
. Any better way to achieve this goal with popen
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自同一手册:
从流中读取命令的标准输出,命令的标准输入与称为popen()您执行的命令 。它试图从您正在运行程序的同一终端中读取。这会创建一个竞赛,但是由于该程序没有读取任何内容,因此
ssh
总是会获胜。然后ssh
将您的输入传递给对其进行解释的远程程序。您可以将命令的标准输入重新定向使用正常的shell语法执行
,但这与
top
和其他期望其标准输入为终端的交互式命令无法使用。From the same manual:
The command you are executing is
ssh
. It tries to read from the same terminal you are running your program from. This creates a race, but since the program doesn't read anything,ssh
always wins. Thenssh
passes your input to the remote program which interprets it.You can redirect the standard input of the command being executed with normal shell syntax
but this will not work with
top
and other interactive commands that expect their standard input to be a terminal.