如何在C中执行shell脚本?

时间:2022-12-06 09:25:23

I'm trying to create a .sh file, write the script to it and then execute it using exec*

我正在尝试创建一个.sh文件,将脚本写入它然后使用exec *执行它

So far, I managed to create the file and write the code to it, but the execl doesn't execute the script

到目前为止,我设法创建文件并将代码写入其中,但execl不执行脚本

int main( int argc, char * argv[] ){
    char str[] = "#!/bin/bash \n echo 'Hello World!'";
    FILE *fp = fopen("script.sh", "w+");
    fwrite(str , 1 , sizeof(str) , fp );
    fclose(fp);
    execl ("/usr/bin/chmod", "chmod", "+x", "script.sh", (char *)0);
    execl ("/export/home/redpal/lab4", "script.sh", (char *)0);
    return 0;
}

Should I put each execl in the child proccess?

我应该把每个execl放在子进程中吗?

2 个解决方案

#1


3  

The execl function (like all exec(3) functions and the execve(2) system call) don't return on success. It would return only on failure.

execl函数(像所有exec(3)函数和execve(2)系统调用)都不会成功返回。它只会在失败时返回。

So your first call:

所以你的第一个电话:

execl ("/usr/bin/chmod", "chmod", "+x", "script.sh", (char *)0);

is very likely to succeed. Then your current program is gone, and your process is running the /usr/bin/chmod program. Once that program finished (in a few milliseconds), your process exits (and your invoking shell gives a new prompt).

很有可能成功。然后你的当前程序消失了,你的进程正在运行/ usr / bin / chmod程序。一旦该程序完成(在几毫秒内),您的进程退出(并且您的调用shell提供了一个新提示)。

Instead of using the /usr/bin/chmod program you should consider using the chmod(2) system call.

您应该考虑使用chmod(2)系统调用,而不是使用/ usr / bin / chmod程序。

The rest of your program is also wrong. You might want to exec the generated script (but then, you need to give its entire path).

你的程序的其余部分也是错误的。您可能希望执行生成的脚本(但是,您需要提供其整个路径)。

You need to understand how to run processes using fork(2), execve(2), waitpid(2) and friend system calls. We cannot explain how to do that (it is too long), but you should read several chapters of the Advanced Linux Programming book (freely downloadable).

您需要了解如何使用fork(2),execve(2),waitpid(2)和朋友系统调用来运行进程。我们无法解释如何做到这一点(它太长了),但你应该阅读高级Linux编程书的几章(可免费下载)。

Perhaps you should consider embedding an interpreter like Lua or Guile in your real program (so your question looks like some XY problem)

也许你应该考虑在你的真实程序中嵌入像Lua或Guile这样的解释器(所以你的问题看起来像是一些XY问题)

And you might just use system(3) or popen(3) to run some command.... Perhaps using something like FILE* cmd = popen("/bin/sh", "w"); might be enough .... Then you'll write shell commands to cmd and you need to pclose(cmd)

你可能只是使用system(3)或popen(3)来运行一些命令....也许使用像FILE * cmd = popen(“/ bin / sh”,“w”)这样的东西;可能就够了....然后你将shell命令写入cmd,你需要pclose(cmd)

#2


2  

Check for errors after each potentially failing command. You should write sizeof(array)-1 bytes into the file, or you'll be also writing the terminating zero.

在每个可能失败的命令后检查错误。您应该将sizeof(array)-1个字节写入文件,或者您也将写入终止零。

exec* syscalls replace process images. If they succeed, your program is replaced by the binary you've just executed. Consequently, you either need to exec in a child process or the exec* syscall needs to be the last thing you do in your program.

exec *系统调用替换过程映像。如果它们成功,您的程序将被您刚刚执行的二进制文件替换。因此,您需要执行子进程,或者exec * syscall需要是您在程序中执行的最后一项操作。

In your case, the chmod execution is entirely avoidable. You can either issue the chmod syscall directly, or you can make sure you create the file in which case you can set the permissions right off the bat.

在您的情况下,chmod执行是完全可以避免的。您可以直接发出chmod系统调用,也可以确保创建文件,在这种情况下,您可以立即设置权限。

I'd it like so:

我喜欢这样:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main( int argc, char * argv[] )
{
    unlink("script.sh"); //unchecked -- let it fail if the file's not there
    int fd;
    if(0>(fd = open("script.sh", O_CREAT|O_WRONLY, 0777)))
        { perror("Couldn't create 'script.sh'"); return EXIT_FAILURE; }
    int nr;
    static char const str[] = "#!/bin/bash \n echo 'Hello World!'";
    size_t to_write = sizeof str - 1;
    if( to_write != (nr=write(fd, str, sizeof str - 1)) || 0>close(fd)  )
        { perror("Couldn't write contents"); return EXIT_FAILURE; }
    //writes to the filesystem on linux aren't ever partial unless there's a filesystem error 
    //otherwise you need to account for partial write (which fwrite does for you)

    execl ("./script.sh", "script.sh", (char *)0);
    perror("Couldn't exec './script.sh'");
    return EXIT_FAILURE;
}

#1


3  

The execl function (like all exec(3) functions and the execve(2) system call) don't return on success. It would return only on failure.

execl函数(像所有exec(3)函数和execve(2)系统调用)都不会成功返回。它只会在失败时返回。

So your first call:

所以你的第一个电话:

execl ("/usr/bin/chmod", "chmod", "+x", "script.sh", (char *)0);

is very likely to succeed. Then your current program is gone, and your process is running the /usr/bin/chmod program. Once that program finished (in a few milliseconds), your process exits (and your invoking shell gives a new prompt).

很有可能成功。然后你的当前程序消失了,你的进程正在运行/ usr / bin / chmod程序。一旦该程序完成(在几毫秒内),您的进程退出(并且您的调用shell提供了一个新提示)。

Instead of using the /usr/bin/chmod program you should consider using the chmod(2) system call.

您应该考虑使用chmod(2)系统调用,而不是使用/ usr / bin / chmod程序。

The rest of your program is also wrong. You might want to exec the generated script (but then, you need to give its entire path).

你的程序的其余部分也是错误的。您可能希望执行生成的脚本(但是,您需要提供其整个路径)。

You need to understand how to run processes using fork(2), execve(2), waitpid(2) and friend system calls. We cannot explain how to do that (it is too long), but you should read several chapters of the Advanced Linux Programming book (freely downloadable).

您需要了解如何使用fork(2),execve(2),waitpid(2)和朋友系统调用来运行进程。我们无法解释如何做到这一点(它太长了),但你应该阅读高级Linux编程书的几章(可免费下载)。

Perhaps you should consider embedding an interpreter like Lua or Guile in your real program (so your question looks like some XY problem)

也许你应该考虑在你的真实程序中嵌入像Lua或Guile这样的解释器(所以你的问题看起来像是一些XY问题)

And you might just use system(3) or popen(3) to run some command.... Perhaps using something like FILE* cmd = popen("/bin/sh", "w"); might be enough .... Then you'll write shell commands to cmd and you need to pclose(cmd)

你可能只是使用system(3)或popen(3)来运行一些命令....也许使用像FILE * cmd = popen(“/ bin / sh”,“w”)这样的东西;可能就够了....然后你将shell命令写入cmd,你需要pclose(cmd)

#2


2  

Check for errors after each potentially failing command. You should write sizeof(array)-1 bytes into the file, or you'll be also writing the terminating zero.

在每个可能失败的命令后检查错误。您应该将sizeof(array)-1个字节写入文件,或者您也将写入终止零。

exec* syscalls replace process images. If they succeed, your program is replaced by the binary you've just executed. Consequently, you either need to exec in a child process or the exec* syscall needs to be the last thing you do in your program.

exec *系统调用替换过程映像。如果它们成功,您的程序将被您刚刚执行的二进制文件替换。因此,您需要执行子进程,或者exec * syscall需要是您在程序中执行的最后一项操作。

In your case, the chmod execution is entirely avoidable. You can either issue the chmod syscall directly, or you can make sure you create the file in which case you can set the permissions right off the bat.

在您的情况下,chmod执行是完全可以避免的。您可以直接发出chmod系统调用,也可以确保创建文件,在这种情况下,您可以立即设置权限。

I'd it like so:

我喜欢这样:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main( int argc, char * argv[] )
{
    unlink("script.sh"); //unchecked -- let it fail if the file's not there
    int fd;
    if(0>(fd = open("script.sh", O_CREAT|O_WRONLY, 0777)))
        { perror("Couldn't create 'script.sh'"); return EXIT_FAILURE; }
    int nr;
    static char const str[] = "#!/bin/bash \n echo 'Hello World!'";
    size_t to_write = sizeof str - 1;
    if( to_write != (nr=write(fd, str, sizeof str - 1)) || 0>close(fd)  )
        { perror("Couldn't write contents"); return EXIT_FAILURE; }
    //writes to the filesystem on linux aren't ever partial unless there's a filesystem error 
    //otherwise you need to account for partial write (which fwrite does for you)

    execl ("./script.sh", "script.sh", (char *)0);
    perror("Couldn't exec './script.sh'");
    return EXIT_FAILURE;
}