Thread: exec a bash script

  1. #1
    Registered User
    Join Date
    May 2011
    Posts
    116

    exec a bash script

    hello!

    I'm writing a C++ program and I use fork() and execl to call a bash script.My .cpp communicates with the script with a pipe in which the script writes data and then the .cpp reads them.I don't think my script is ever executed the way I'm doing it...

    Code:
            int pid;
    	int res = mkfifo (pipeName, 0666); 
    	if (res < 0) {
    		perror("Error creating the named pipe");
    		exit (2);
    	}
    	
    	pid=fork();
    	if(pid<0)
    	{
    		cerr << "Failed to fork" << endl;
    		exit(1);
    	}
    
    	if(pid==0){
    		
    		execl("./bbb","bbb",argv[1],pipeName,NULL);
    		exit(0);
    	}
    where pipeName is the name of the pipe .cpp and bash script communicate with,argv[1] is just a string,bbb is the name of the script

    In my script when I want to write something to the pipe I do

    Code:
    echo $var2 >> $2
    where $2 is the name of the pipe the script got when called.

    When I run it it seems to meet a deadlock so I figured maybe the script is never called...
    Any ideas?

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    A bash script should not be executed directly with execl. It is a file that is interpreted by the bash shell. So you need to execute the bash shell, with the name of a script as first argument (and subsequent arguments after that).

    If the bash shell is not installed on your system, all bets are off.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by grumpy View Post
    A bash script should not be executed directly with execl. It is a file that is interpreted by the bash shell. So you need to execute the bash shell, with the name of a script as first argument (and subsequent arguments after that).

    If the bash shell is not installed on your system, all bets are off.
    Could you please give me an example of what you mean exactly?
    Actually now my execl works fine and the script does what it has to do (write to files)
    But when I change the output the script writes to and instead of a file I choose the pipe that .cpp and script use to communicate (the name of the pipe is passed to script as an argument of execl) the script isn't working..

    I do exactly the same I did in order to write to file:

    Code:
    echo $line >> tempfile
    --tempfile is a simple file my script writes to---

    Code:
    echo $line >> $2
    --$2 is the name of the pipe the script takes as an argument--

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by quo View Post
    Could you please give me an example of what you mean exactly?
    His point, (or what I understood ) was to do something like this :
    Code:
    execl("/bin/bash","bash","/home/manasij7479/init.sh",nullptr);
    (Your other args go between the script's name and the null pointer)
    Last edited by manasij7479; 06-01-2012 at 05:47 AM.

  5. #5
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by manasij7479 View Post
    His point, (or what I understood ) was to do something like this :
    Code:
    execl("/bin/bash","bash","/home/manasij7479/init.sh",nullptr);
    (Your other args go between the script's name and the null pointer)
    ok thank you
    but since it works now do I have to change it?
    Also,how can a script write to a pipe that was created in the .cpp and sent to the script through exec?

  6. #6
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by quo View Post
    ok thank you
    but since it works now do I have to change it?
    I don't know if the 'working' is standard or accidental.
    Also,how can a script write to a pipe that was created in the .cpp and sent to the script through exec?
    Your way of creating a pipe specifies a filename (and its full path). Just use normal File IO from the script.
    The 'file' is created as some sort of special object for the communication.
    Read "man 3 mkfifo" if you're confused.

  7. #7
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by manasij7479 View Post
    I don't know if the 'working' is standard or accidental.

    Your way of creating a pipe specifies a filename (and its full path). Just use normal File IO from the script.
    The 'file' is created as some sort of special object for the communication.
    Read "man 3 mkfifo" if you're confused.

    I just can not understand why the script cannot write to the pipe since it represents a file.Why the simple echo command works for any other regular file but not for the pipe?

    Code:
    echo things >> pipeName
    pipename is argument $2 for the script since it's sent from .cpp

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Hey gang:

    Code:
    #!/bin/bash
    Shebang. Presuming the script starts with that (they usually do), you do not need to invoke "bash script.sh"; the shebang is not interpreted by the shell, it's interpreted by the "loader", which according to this is the (kernel) handler for the execve() system call:

    Loader (computing) - Wikipedia, the free encyclopedia

    See also:

    Shebang (Unix) - Wikipedia, the free encyclopedia

    Y'all should really test your premises before you give advice .

    Quote Originally Posted by quo View Post
    since it works now do I have to change it?
    If your script starts with a shebang, you don't have to change it; grumpy was jumping to an erroneous conclusion. Using the version explicitly invoking bash will work, but it amounts to exactly the same thing and is not at all necessary. No one writes shell scripts without a shebang at the beginning.

    Also,how can a script write to a pipe that was created in the .cpp and sent to the script through exec?
    It's a named fifo, right? Open it and write to it like a file.
    Last edited by MK27; 06-01-2012 at 07:58 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by MK27 View Post
    Shebang. Presuming the script starts with that (they usually do), you do not need to invoke "bash script.sh"; the shebang is not interpreted by the shell, it's interpreted by the "loader", which according to this is the (kernel) handler for the execve() system call:

    Y'all should really test your premises before you give advice .
    Doesn't that only apply for those exec functions taking a file as the argument ? .and not a path for the binary ?
    Quote Originally Posted by man 3 exec
    int execl(const char *path, const char *arg, ...);
    int execlp(const char *file, const char *arg, ...);
    int execle(const char *path, const char *arg,
    ..., char * const envp[]);
    int execv(const char *path, char *const argv[]);
    int execvp(const char *file, char *const argv[]);
    int execvpe(const char *file, char *const argv[],
    char *const envp[]);
    Last edited by manasij7479; 06-01-2012 at 07:58 AM.

  10. #10
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by MK27 View Post
    It's a named fifo, right? Open it and write to it like a file.
    Thanks for your help!Since it's the first time I handle a pipe through a script I didn't open it I just wrote to it.
    How do we open a pipe in a bash script?
    thank you

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by manasij7479 View Post
    Doesn't that only apply for those exec functions taking a file as the argument ? .and not a path for the binary ?
    A path to a binary is a file path; a binary is a file. These are the same thing (note, the script must have a shebang indicating the interpreter and be marked as an executable, which shell scripts usually also are). There is not one loader* for execve and then some other loader for everything else, it is just that the "e" functions include an additional parameter (environment variables, which are also not just part of the shell, altho it is common to think of them in relation to shell access via globals).

    Certainly this works fine:

    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main(void) {
    	char *args[] = { "test.sh", NULL };
    	execv("/home/scripts/test.sh", args);
    	
    	return 0;
    }
    You can try it with all the other "exec" functions too if you want...

    * note this is not the same thing as the dynamic (library) loader potentially invoked for binaries after the kernel handler/loader has loaded the binary into memory and began its work.
    Last edited by MK27; 06-01-2012 at 08:20 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by quo View Post
    Thanks for your help!Since it's the first time I handle a pipe through a script I didn't open it I just wrote to it.
    How do we open a pipe in a bash script?
    thank you
    Code:
    mkfifo myfifo.fifo # you don't have to do that if it exists already
    echo "hello world" > myfifo.fifo
    The last line blocks, however; it won't return until another process reads from the pipe. But if you don't want to wait or need to synchronize, you can put & at the end to fork it into the background.
    Last edited by MK27; 06-01-2012 at 08:22 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by MK27 View Post
    The last line blocks, however; it won't return until another process reads from the pipe. But if you don't want to wait or need to synchronize, you can put & at the end to fork it into the background.

    yes it works now.I noticed that it blocks and it's a bit strange because I have a while loop in the script which does many echos in the pipe.On the other hand I have the following while loop in the .cpp
    which reads the lines of the pipe

    Code:
    while(child.getline(line,LINESIZE)){
    		cout<<line<<endl;		
    	}
    child.close();
    but it only prints 2lines(although in the script are many echo commands) and then blocks

  14. #14
    Registered User
    Join Date
    May 2011
    Posts
    116
    Quote Originally Posted by MK27 View Post
    Code:
    mkfifo myfifo.fifo # you don't have to do that if it exists already
    echo "hello world" > myfifo.fifo
    The last line blocks, however; it won't return until another process reads from the pipe. But if you don't want to wait or need to synchronize, you can put & at the end to fork it into the background.
    I tried to solve the deadlock so I added a sleep(1) in the while loop of getline in my.cpp and it runs ok.But the thing is that sometimes my script has many echo commands maybe 500 or more and
    if for each echo the getline sleeps for 1 then it's very slow..
    Any other suggestions?

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by quo View Post
    Any other suggestions?
    Is it necessary to put the echo in the while loop or could you concatenate all the data there instead then and echo it all at once afterward?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Awk and sed bash script help
    By Annonymous in forum Linux Programming
    Replies: 19
    Last Post: 05-10-2012, 12:40 AM
  2. ssh/bash script question
    By Overworked_PhD in forum Tech Board
    Replies: 2
    Last Post: 03-30-2009, 07:48 PM
  3. Bash Script Q
    By QuestionC in forum Tech Board
    Replies: 1
    Last Post: 04-19-2007, 10:16 AM
  4. Linux: Use C to call a bash script
    By harada in forum Linux Programming
    Replies: 9
    Last Post: 10-27-2006, 01:59 PM
  5. Running 'exec' twice in one UNIX shell script
    By Zughiaq in forum Tech Board
    Replies: 2
    Last Post: 05-03-2003, 12:04 AM