2

I am spinning up a linux virtual environment which is missing the needed drivers, so I am using the shell to install. I am doing this manually but would like to automate it from within R, where the rest of my code is.

I am able to open the shell in R by clicking on Tools>Shell...

I then have multiple lines of Bash script to run in order to install the "ODBC Driver 17 for SQL Server"

sudo su 
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/debian/8/prod.list > /etc/apt/sources.list.d/mssql-release.list

exit
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install msodbcsql17

I would like to save these commands in some sort of readable file and run this from within R.

After some search I have seen posts that use System to run a single line but I have not been able to find information on if/how this can be extended to run multiple lines or how to pull these commands from some sort of saved file.

Context: I am new to linux and Bash/Shell commands Thank you!

Dave
  • 410
  • 6
  • 13
  • 2
    You can chain all commands on one line using `;` as separator. – Ralf Stubner Jun 25 '18 at 18:19
  • Thanks @RalfStubner. When calling `system("sudo su; whoami")` I get `username` and not as expected `root` as I would have gotten with successive commands in the shell. Similarly chaining the code with `;` from my question above fails as permissions aren't carried through. How can I keep the permissions as I chain with `;`? – Dave Jun 25 '18 at 18:33
  • Indeed, `sudo su` is special. You don’t need it if you call `curl ...| sudo apt-key ...` and `curl ...| sudo tee ... ` instead. – Ralf Stubner Jun 25 '18 at 19:46
  • Thank you @RalfStubner. I'm not sure If I understood your answer fully. I think this has become it's [own question](https://stackoverflow.com/questions/51032052/sudo-su-command-discrepancy-in-rstudio-shell-vs-system-function). Hopefully an answer there will help clarify for myself and for others. Would love your input there, if you have the chance. Thank you! – Dave Jun 25 '18 at 21:42

2 Answers2

1

You can separate commands using ; and just store the entire script as a single character string. If you have special characters in your script (you don't currently) you are going to have to be very careful about correctly using escape characters.

For your bash script something like this should work

command="sudo su ; 
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -; 
curl https://packages.microsoft.com/config/debian/8/prod.list > /etc/apt/sources.list.d/mssql-release.list; 
exit;
sudo apt-get update;
sudo ACCEPT_EULA=Y apt-get install msodbcsql17;"

system(command)

Another workaround is to save your script as a .sh bash script and just call the script filename within command(). Note that to make the bash script executable from the command line, you have to add the she-bang line (#!/bin/bash) at the very top.

Ajjit Narayanan
  • 632
  • 2
  • 8
  • 18
  • Thank you, very helpful! Running this code gives me the `(23) Failed writing body` due to permission not carrying from `sudo su` Please see my comment / question about permissions above on the OP for further details. – Dave Jun 25 '18 at 18:41
  • 1
    Hmm, another workaround is to save your script as a .sh bash script and just call the script filename within `command()`. Note that to make the bash script executable, you have to add the she-bang line ( `#!/bin/bash` ) at the very top. Or just follow Dave's suggestion above. – Ajjit Narayanan Jun 25 '18 at 19:48
  • So I have created a .sh bash script and I am calling it via `system(command = "./driver_load.sh")`. I am still getting that same Error:`ERROR: This command can only be used by root.` and `(23) Failed writing body`. This is very strange as running the same code line by line from the shell does indeed work – Dave Jun 25 '18 at 20:23
  • I have opened [another question](https://stackoverflow.com/questions/51032052/sudo-su-command-discrepancy-in-rstudio-shell-vs-system-function?noredirect=1#comment89056646_51032052) to address this issue. If you edit your answer to include your insights on executing a script, it would better answer the original question and I can accept your answer – Dave Jun 25 '18 at 21:49
1

Actually multi-line commands work just fine:

command <- "cd
pwd
ls"
system(command)

The problem with the commands provided by MS is the (unnecessary) use of su. You can rewrite the commands to use elevated privileges only where necessary:

command="curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/debian/8/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install msodbcsql17"
system(command)

see for example here for sudo tee.

Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • 1
    This worked, thank you! Just to augment this solution in case other people see are looking for an answer to the original question, I see that I can save these commands in a bash script e.g. load_driver.sh and then call this with R's `system(command = "./load_driver.sh")`. Also don't forget to make this file executable in bash before running in R: `chmod +x load_driver.sh` – Dave Jun 26 '18 at 15:25