Установка пакетов R с помощью скрипта bash - ответы на запросы
На моей работе сервер пограничного узла, который обращается к нашему кластеру, обновляется каждый день. Это означает, что я должен клонировать наш репозиторий и устанавливать кучу пакетов R каждое утро. Я написал bash-скрипт (используя https://github.com/eddelbuettel/littler для открытия R из командной строки), чтобы автоматизировать это, и он работает, за исключением одного сбоя.
Bash называет: r install.R
который открывает сеанс R и вызывает следующую команду:
repos <- "http://... [our CRAN equivalent]"
install.packages("[package_name]",repos)
Теперь, обычно, если бы я сам вводил это в R, я получил бы это как ответ:
Installing package into ‘/usr/hdp/2.5.5.3-2/spark2/R/lib’ (as ‘lib’ is unspecified)
Warning in install.packages("[name_of_package]", repos = "http://...") :
'lib = "/usr/hdp/2.5.5.3-2/spark2/R/lib"' is not writable
Would you like to use a personal library instead? (y/n)
И я бы сказал "у", а затем "у", когда он предлагает создать библиотеку. Однако, когда я делаю это из скрипта bash, он просто говорит, что библиотека недоступна для записи и прерывает работу.
Здесь я вижу два варианта: 1) Я сообщаю ему, в какую библиотеку записывать пакеты. Я пробовал это, и хотя пакеты шли туда, они пришли пустыми. На самом деле ничего не было загружено из репо.
2) Каким-то образом получить сценарий, чтобы иметь возможность передать два положительных ответа, которые мне нужны, чтобы позволить R сделать свое дело и создать свою собственную библиотеку.
Любые предложения по любому из них будут высоко оценены!
4 ответа
Другой подход, который работает гораздо лучше, чем я писал ранее:
В Баш:
Создайте определенную библиотеку для установки (то же самое, что и R по умолчанию, который нужно создать)
mkdir -p R/x86_64-pc-linux-gnu-library/3.3
Rscript --vanilla install_packages.R
В install_packages.R:
pkg_list <- # however you want to get this
for (pkg in pkg_list) {
install.packages(pkg, repos = "your_cran_mirror",
lib = "R/x86_64-pc-linux-gnu-library/3.3")
if (!require(pkg, character.only = T)) {
quit(save = "no", status = 1, runLast = FALSE)
}
}
Используя этот метод, R не будет запрашивать вас, и ваш скрипт будет работать так, как задумано.
Есть несколько решений для этого. Я покажу два аналогичных решения.
Интерактивный скрипт:
#!/bin/bash
# test.sh
printf "Response 1: "
read resp1
echo "You inserted $resp1"
printf "Response 2: "
read resp2
echo "You inserted $resp2"
Чтобы передать две записи в этот скрипт, мы можем использовать строку здесь:
$ ./test.sh <<< $'yes\nno\n'
Response 1: You inserted yes
Response 2: You inserted no
Каждая запись отделяется от других записей знаком \n. Эта строка отправляется на стандартный ввод скрипта.
В качестве альтернативы, вы также можете передать строку в поток скриптов stdin:
$ printf 'yes\nno\n' | ./test.sh
Response 1: You inserted yes
Response 2: You inserted no
Два варианта:
yes | r install.R
или же:
{ echo y; echo y; } | r install.R
ПРИМЕЧАНИЕ: это технически работает, но очень неуклюже и подвержено ошибкам. Пожалуйста, посмотрите мой другой ответ.
Я нашел способ сделать это.
Сначала создайте или измените .Rprofile. Добавьте установки и ответы вверху этого файла. Например:
repos = [CRAN or wherever you're sourcing from]
install.packages(package1, repos)
y
y
install.packages(package2, repos)
install.packages(package3, repos)
... # etc.
Символ 'y' необходим только для первого пакета, когда R спрашивает, хотите ли вы создать новую библиотеку. Последующие пакеты также будут добавлены туда.
Если вы действительно хотите, чтобы он был свободным от рук, и после установки пакетов R скрипт выполняет другие действия, вы можете добавить quit()
оператор в конце, который выйдет из R и сделает все, что вы хотите, чтобы скрипт делал. Это может раздражать, если вы хотите запустить R позже, поэтому вы хотите, чтобы скрипт передавал пару разных.Rprofiles.
Во-вторых, в вашем скрипте bash просто откройте R с R
,.Rprofile будет запущен сразу после запуска, и пакеты будут загружены автоматически.