Possibly broken system2 env-option

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Possibly broken system2 env-option

Henning Bredel
Hey all,

what is wrong with this command:

  system2("echo", env = c(VAR = "Hello World"), args = c("$VAR"))

I am a bit confused, as help("system2") writes about the env option:

> character vector of name=value strings to set environment variables.

Is this option buggy, or am I using it just wrong?

Thanks for your help

  Henning

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Gábor Csárdi
Probably not broken, just hard to get the quoting right? Or it does
not work with echo?

It is surely hard to get it right, I have been trying for 15 minutes.I
am pretty sure that the correct form is env = "VAR='Hello-World'" but
spaces and other special characters might cause trouble. E.g. this
works, but only without spaces (px is an internal tool for testing,
that can get an env var, and it is portable):

❯ px <- processx:::get_tool("px")
❯ system2(px, c("getenv", "VAR"), env = "VAR=foo")
foo

❯ system2(px, c("getenv", "VAR"), env = c(VAR="Hello World"))
sh: Hello: command not found
Warning message:
In system2(px, c("getenv", "VAR"), env = c(VAR = "Hello World")) :
  error in running command

Somebody with more system2() experience can probably fix this, but
here is an alternative, using the processx package:

❯ processx::run(px, c("getenv", "VAR"), env = c(Sys.getenv(), VAR =
"Hello World"))
$status
[1] 0

$stdout
[1] "Hello World\n"

$stderr
[1] ""

$timeout
[1] FALSE

For processx, you don't need to quote anything (i.e. command,
arguments or env vars), because it does not
use an intermediate shell.

Disclaimer: I am an author of processx.

Gabor

On Tue, Mar 19, 2019 at 9:28 AM Henning Bredel <[hidden email]> wrote:

>
> Hey all,
>
> what is wrong with this command:
>
>   system2("echo", env = c(VAR = "Hello World"), args = c("$VAR"))
>
> I am a bit confused, as help("system2") writes about the env option:
>
> > character vector of name=value strings to set environment variables.
>
> Is this option buggy, or am I using it just wrong?
>
> Thanks for your help
>
>   Henning
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Peter Dalgaard-2
In reply to this post by Henning Bredel
You are using it wrong. It wants strings of the form "name=value", not a character vector with names as labels. So this is closer to the mark:

> system2("echo", env = c("VAR='Hello World'"), args = c("$VAR"))

>

However, as you see it doesn't work as intended. The problem is that the $-substitution refers to the environment of the shell executing the command. I.e. this does not work from a terminal command line either:

pd$ VAR="foo" echo $VAR

pd$

Or even

pd$ VAR="bar"
pd$ VAR="foo" echo $VAR
bar

What you need is something like (NB: single quotes!)

pd$ VAR="foo" sh -c 'echo $VAR'
foo

So:

> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
Hello World

-pd

> On 18 Mar 2019, at 17:28 , Henning Bredel <[hidden email]> wrote:
>
> Hey all,
>
> what is wrong with this command:
>
>  system2("echo", env = c(VAR = "Hello World"), args = c("$VAR"))
>
> I am a bit confused, as help("system2") writes about the env option:
>
>> character vector of name=value strings to set environment variables.
>
> Is this option buggy, or am I using it just wrong?
>
> Thanks for your help
>
>  Henning
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

--
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Office: A 4.23
Email: [hidden email]  Priv: [hidden email]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Gábor Csárdi
On Tue, Mar 19, 2019 at 9:59 AM peter dalgaard <[hidden email]> wrote:
[...]
> What you need is something like (NB: single quotes!)
> > system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
> Hello World

Just out of curiosity, do you think it is possible to make this
portable, assuming sh is available? On Windows it gives

> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
/rtools34/bin/sh: VAR=Hello World: No such file or directory
Warning message:
running command '"sh" VAR='Hello World' -c 'echo $VAR'' had status 127

G.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Peter Dalgaard-2
     On Windows, ‘env’ is only supported for commands such as ‘R’ and
     ‘make’ which accept environment variables on their command line.

So I suppose that would be tricky.

The basic issue is that on Unix-alikes, system2 constructs a command like

FOO=bar cmd args

and passes that to sh via system(). On windoes, system() does not call sh, so system2() does (effectively)

cmd FOO=bar args

and hopes that cmd knows what to do with the env setting.

-pd

> On 19 Mar 2019, at 11:09 , Gábor Csárdi <[hidden email]> wrote:
>
> On Tue, Mar 19, 2019 at 9:59 AM peter dalgaard <[hidden email]> wrote:
> [...]
>> What you need is something like (NB: single quotes!)
>>> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
>> Hello World
>
> Just out of curiosity, do you think it is possible to make this
> portable, assuming sh is available? On Windows it gives
>
>> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
> /rtools34/bin/sh: VAR=Hello World: No such file or directory
> Warning message:
> running command '"sh" VAR='Hello World' -c 'echo $VAR'' had status 127
>
> G.

--
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Office: A 4.23
Email: [hidden email]  Priv: [hidden email]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Gábor Csárdi
Right. I suppose, one thing you can do is setting the env var in the
current process, call system2() and then unset/restore the env var.
This is unlikely to cause problems, unless your R process is
multi-threaded, and the env var causes troubles in the other threads.
The withr package makes setting the temporary env var convenient, but
it is easy to write your own with_envvar() function:

withr::with_envvar(
  c(VAR = "Hello world"),
  system2("sh", "-c 'echo $VAR'"))

This seems to be portable, at least it works on macOS and Windows.

G.


On Tue, Mar 19, 2019 at 10:44 AM peter dalgaard <[hidden email]> wrote:

>
>      On Windows, ‘env’ is only supported for commands such as ‘R’ and
>      ‘make’ which accept environment variables on their command line.
>
> So I suppose that would be tricky.
>
> The basic issue is that on Unix-alikes, system2 constructs a command like
>
> FOO=bar cmd args
>
> and passes that to sh via system(). On windoes, system() does not call sh, so system2() does (effectively)
>
> cmd FOO=bar args
>
> and hopes that cmd knows what to do with the env setting.
>
> -pd
>
> > On 19 Mar 2019, at 11:09 , Gábor Csárdi <[hidden email]> wrote:
> >
> > On Tue, Mar 19, 2019 at 9:59 AM peter dalgaard <[hidden email]> wrote:
> > [...]
> >> What you need is something like (NB: single quotes!)
> >>> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
> >> Hello World
> >
> > Just out of curiosity, do you think it is possible to make this
> > portable, assuming sh is available? On Windows it gives
> >
> >> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
> > /rtools34/bin/sh: VAR=Hello World: No such file or directory
> > Warning message:
> > running command '"sh" VAR='Hello World' -c 'echo $VAR'' had status 127
> >
> > G.
>
> --
> Peter Dalgaard, Professor,
> Center for Statistics, Copenhagen Business School
> Solbjerg Plads 3, 2000 Frederiksberg, Denmark
> Phone: (+45)38153501
> Office: A 4.23
> Email: [hidden email]  Priv: [hidden email]
>
>
>
>
>
>
>
>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

Henning Bredel
In reply to this post by Peter Dalgaard-2
Okay, thanks for clarification.

On 3/19/19 10:51 AM, peter dalgaard wrote:

> You are using it wrong. It wants strings of the form "name=value", not a character vector with names as labels. So this is closer to the mark:
>
>> system2("echo", env = c("VAR='Hello World'"), args = c("$VAR"))
>
>>
>
> However, as you see it doesn't work as intended. The problem is that the $-substitution refers to the environment of the shell executing the command. I.e. this does not work from a terminal command line either:
>
> pd$ VAR="foo" echo $VAR
>
> pd$
>
> Or even
>
> pd$ VAR="bar"
> pd$ VAR="foo" echo $VAR
> bar
>
> What you need is something like (NB: single quotes!)
>
> pd$ VAR="foo" sh -c 'echo $VAR'
> foo
>
> So:
>
>> system2("sh", env = c("VAR='Hello World'"), args = c("-c 'echo $VAR'"))
> Hello World
>
> -pd
>
>> On 18 Mar 2019, at 17:28 , Henning Bredel <[hidden email]> wrote:
>>
>> Hey all,
>>
>> what is wrong with this command:
>>
>>  system2("echo", env = c(VAR = "Hello World"), args = c("$VAR"))
>>
>> I am a bit confused, as help("system2") writes about the env option:
>>
>>> character vector of name=value strings to set environment variables.
>>
>> Is this option buggy, or am I using it just wrong?
>>
>> Thanks for your help
>>
>>  Henning
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
l o
Reply | Threaded
Open this post in threaded view
|

Re: Possibly broken system2 env-option

l o
In reply to this post by Henning Bredel
Studying Professor Dalgaard's code a bit, here is a little hack that
returns the desired result on Unix-alikes:

From

>* system2("echo", env = c("VAR='Hello World'"), args = c("$VAR"))*

to

>* system2("echo", env = c("VAR='Hello World';"), args = c("$VAR"))*
Hello World

That is, adding the semi-colon effectively transforms

pd$ VAR="foo" echo $VAR

to

pd$ VAR="foo"; echo $VAR


Maybe this doesn't apply to more complicated situations,though.

luke

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel