1

Consider the script:

#!/bin/bash

fun() {
  echo "hello $1"
}

echo "fun world" | parallel

Now, the function fun is not available in the script echoed by echo.

Is there a way to make it available / export it?

Edit: See GNU parallel

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • Nothing you aren't going to have to jump through at least half a dozen hoops to make work. – Ignacio Vazquez-Abrams Jan 10 '18 at 18:07
  • @PesaThe The string `"fun world"` is a small script. – bitmask Jan 10 '18 at 18:08
  • 2
    Can you explain more on your requirement. It is quite vague (atleast to me) – Inian Jan 10 '18 at 18:09
  • A true "subshell" is a shell that's `fork()`ed from the main shell with no intervening `exec`-family syscall. Those have *all* functions available. – Charles Duffy Jan 10 '18 at 18:11
  • ...if you mean "a shell started by the `parallel` command" (which doesn't fit into the traditional definition of "subshell"), then we're in the space of `export -f`, and this question is duplicative of https://stackoverflow.com/questions/2199455/bash-how-to-call-a-function-declared-in-a-parent-shell – Charles Duffy Jan 10 '18 at 18:12
  • Also pertinent: https://stackoverflow.com/questions/23814360/gnu-parallel-and-bash-functions-how-to-run-the-simple-example-from-the-manual – Charles Duffy Jan 10 '18 at 18:16
  • @bitmask, if you believe the flagged duplicates don't answer your question, please [edit] to describe how you attempted to apply their advice, and the exact errors encountered during those attempts. – Charles Duffy Jan 10 '18 at 18:24
  • 1
    @bitmask, btw, for future reference: `parallel` is not part of bash, not *written in* bash, and otherwise not covered in the bash tag -- there's a whole separate tag for questions about GNU Parallel, and in the future, asking questions about it with that tag is likely to get a better reception. – Charles Duffy Jan 10 '18 at 18:24
  • Replace `parallel` with `env_parallel` and it works. You will, however, need to activate `env_parallel` once, by using `env_parallel --install`, and starting a new shell. – Ole Tange Jan 10 '18 at 23:22

1 Answers1

1

You have the function name inside quotes, the correct syntax is:

echo $(fun world) | parallel

The output from the echo ("hello world") will be passed to parallel through the pipe, so it will be up it it to do something with it.

EDIT:

I might have misunderstood. If you want a script called parallel to execute the function then there are a few issues. If bash then you need to export it as @CharlesDuffy said:

export -f fun

but beware that not all shells support exported functions, so be sure that parallel is a bash script.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • or `fun world | parallel`. – Cyrus Jan 10 '18 at 18:12
  • 1
    @Cyrus: yup, not sure why the OP want's an `echo`, I took that to be a simplification. – cdarke Jan 10 '18 at 18:13
  • I'm assuming that the OP wants `parallel` to start a shell that in turn runs the function. That's not an unreasonable request -- GNU parallel actually has explicit support for this kind of thing (though I'd rather it didn't -- part of why I prefer `xargs -P` is GNU Parallel's approach of throwing in every conceivable feature). – Charles Duffy Jan 10 '18 at 18:13
  • @CharlesDuffy: Ah, I hadn't thought of that. – cdarke Jan 10 '18 at 18:14
  • No, I want `fun` to be run by `parallel`. This runs `hello world` in `parallel`. – bitmask Jan 10 '18 at 18:15
  • @bitmask, note that when a program calls another program, the OS-level interface used to do that is the `execv` syscall. That syscall takes the name of an executable to start -- at that low-level interface, there is absolutely no way to invoke a shell function from any program that isn't a shell interpreter, *unless you pass the executable name of a shell able to interpret that function*. That's the general rule, though -- `parallel` is full of contextually-dependent magic, so rules often don't apply to it. – Charles Duffy Jan 10 '18 at 18:19
  • Just found the Linux `man` page for it. It has an example: `parallel sh -c "echo hi; sleep 2; echo bye" -- 1 2 3` and that should work if the `sh` is replaced by `bash` and the function is exported. – cdarke Jan 10 '18 at 18:21
  • @CharlesDuffy: actually, if the function is exported then it can be picked-up from the environment. Many moons ago I wrote a Perl script to translate (to Perl) and execute a bash function that had been exported. It was as horrible as it sounds. No, wait, it was worse. – cdarke Jan 10 '18 at 18:25
  • @cdarke, sure, but what I said above is that you still need to have a program that "is a shell interpreter". In the example you give, you wrote one (or at least a momentarily adequate subset) in Perl. – Charles Duffy Jan 10 '18 at 18:27
  • @CharlesDuffy: sorry I mis-read your comment. – cdarke Jan 10 '18 at 18:28
  • It appears to work with `export -f`. – bitmask Jan 10 '18 at 18:36
  • If you prefer not to use `export -f` then replacing `parallel` with `env_parallel` will work, too. You just need to activate it: `env_parallel --install; bash`. – Ole Tange Jan 10 '18 at 23:25