6

I'm trying to run a script from URL as root with this command:

sudo bash <(curl -s http://copy.com/gLVZIqUubzcS/popcorn)

But I'm getting this error:

bash: /dev/fd/63: Aucun fichier ou dossier de ce type

French for "not found". Any ideas what it might be?

P.S: I'm running Ubuntu 12.04

2 Answers 2

6

sudo closes all open file descriptors other than stdin, stdout and stderr (see man sudo) so process substitution does not work OOTB with sudo.

Compare

$ sudo bash <(echo echo foo)
bash: /dev/fd/63: No such file or directory

and

$ bash <(echo echo foo)
foo

You can work around this (or use the -C flag to sudo), but doing what you are trying to do is bad - albeit common - practice anyway. If you really just want to run the installer, get a root-shell first and then run the rest without sudo.

1
  • Many thanks man! But it says I'm not permitted to use the -C option. I think I'm doing it wrong.. To what number should I set the fd?
    – pr.nizar
    Commented Apr 15, 2014 at 7:31
3

Don't use process substitution like that. In practice, it's pretty much just this anyway:

sudo sh <<CURL_SCRIPT
    $(curl -s http://copy.com/gLVZIqUubzcS/popcorn)
CURL_SCRIPT

Or:

curl -s http://copy.com/gLVZIqUubzcS/popcorn | sudo sh

Unless the script you're trying to run makes use of bashisms the above will work. If it does use bash-only syntax you should do:

curl -s http://copy.com/gLVZIqUubzcS/popcorn | sudo . /dev/stdin

Though the above doesn't seem to work, which I expect is due to sudo not liking the shell's built-in .dot.

So do this:

curl -s http://copy.com/gLVZIqUubzcS/popcorn | sudo ${0#-} /dev/stdin

You could also simply do:

sudo sh -c "$(curl -s http://copy.com/gLVZIqUubzcS/popcorn)"

You don't need to invoke the bash executable again when you can use the shell's built-ins instead.

12
  • Many thanks! Actually the script does use much of bashisms. The last method actually worked but I have to adapt my script to sh. Thanks!
    – pr.nizar
    Commented Apr 15, 2014 at 7:36
  • 1
    @pr.nizar the ${0#-} will work as well.
    – mikeserv
    Commented Apr 15, 2014 at 8:44
  • Thank you! Yep it does! Just one more question: how to pass an argument to the script with that: sudo bash -c "$(curl -s http://copy.com/gLVZIqUubzcS/popcorn)"? I can't figure it out!
    – pr.nizar
    Commented Apr 15, 2014 at 15:35
  • 1
    @pri.nizar In that case you should use a function, and call its positionals after the script is fully loaded. Other wise you could stream in the definition on a separate file descriptor in a here-doc. Or save your params to a variable and call it afterward. Honestly, the possible solutions from my perspective are too numerous to enumerate, but that's mostly because I don't really know what you're doing. If you could specify? I'd be happy to visit any link you provide me. Perhaps in another question? Describe the workflow from start - finish and the purpose for it? And yes, that's how -c works.
    – mikeserv
    Commented Apr 16, 2014 at 14:12
  • 1
    @pri.nizar - this is approaching other question territory, but if you need to pass arguments then you need to configure your script to handle parameters or environment variables, or to accept arguments over stdin. Understand that because you do not chmod +x a file you do not exec the script but rather a shell that sources your script. This is not a very serious limitation - all shell scripts are just interpreted text files anyway - but the process is initialized a little differently and so arg handling will differ. I think the pipe would work better than than -c though.
    – mikeserv
    Commented Apr 16, 2014 at 14:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .