这几天在做测试,用脚本比较容易些。
但是在此过程中遇到一些问题,也引发出对管道的重新思考。
脚本需要实现的功能描述:
1,循环上100次
2,每次,都需要运行一个服务器上的程序(就叫J程序吧)
都需要输入密码
问题:
这里需要从脚本里往J里输入密码,这里我不会。
我的问题集中在,怎么往标准输入中写入数据。
好,我在脚本中这样写的:
“password" >/dev/fd/0
但shell把“password" 当做命令来处理。我想它可能是,用exec来执行“password" 的。
然后,echo “password" >/dev/fd/0
还是不行,直接打印出来了。
===================================================================================
1,验证为什么不行
我想原因是什么?shell那么常用,不应该不会有这么一个东东的。
接着我写了一个c语言的程序,来验证,echo “password" >/dev/fd/0为什么没写到子程序的标准输入里。
#include <stdio.h>
#include <unistd.h>
void main()
{
pid_t pid;
char s[10] = {0};
if ((pid = fork()) == 0) {
// child
scanf ("%s", s);
printf ("%s\n", s);
while (1);
} else {
// parent
scanf ("%s", s);
printf ("-----%s\n", s);
while (1);
}
}
这里得到的启示是:父子程序对fd其实也存在抢占的,如果父进程先得到标准输入,那么他会把标准输入队列里的东东拿干净。。。原来如此。。。
2,寻找另外的出路
管道,试了
echo "password" | J
成功了。
3,为什么
要弄懂为什么就要确定问题是什么:
①什么是管道
这是在网上找的管道的实现
#include <stdio.h>
#include <unistd.h>
int fd[2];
char *argv[] = {"ls", (char*)0};
char *envp[] = {"PATH=/bin", 0};
char *argv2[] = {"wc", (char*)0};
char *envp2[] = {"PATH=/bin", 0};
void run_ls()
{
dup2(fd[1], 1);
close (fd[0]);
close (fd[1]);
execve("/bin/ls", argv, envp);
}
void run_wc()
{
dup2(fd[0], 0);
close (fd[0]);
close (fd[1]);
execve("/usr/bin/wc", argv2, envp2);
}
int main()
{
pipe(fd);
if (fork() == 0) {
run_ls();
} else {
run_wc(); // 如果标准输入没有东东的话,就会阻塞。所以不用考虑父子进程谁先执行。
}
return 0;
}
解决了。
4,后续:
后面还有很多内容要学习,比如高级一点的expect等,高级一点的进程间通信的概念。
最近有很多东西,要学习,这里的后续放到有空的时候吧。
5,重定向也能实现往进程中传数据的功能
echo "1 2 3" > file.txt
wc < file.txt
注意,这里重定向的话,一定是命令或者执行程序写在前面。不能写成: file.txt > wc。