У меня есть строгий скрипт, которому нужна библиотека в банке. Как добавить это в путь к классам? Я хочу, чтобы скрипт был исполняемым, поэтому я использую #!/usr/bin/env groovy
в верхней части моего скрипта.Как включить баночки в groovy-скрипт?
ответ
Если вы действительно должны вы также можете загрузить JAR во время выполнения с:
this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())
Хех, определенно пропустил раздел «Добавление вещей в класс пути» в первый раз, когда я это прочитал. – timdisney 2008-11-20 17:43:02
Я не мог заставить этот загрузчик классов работать ... кто-нибудь еще мог его использовать? – Zombies 2010-04-23 15:18:35
Существуют ограничения, не описанные в документации при работе с shebang (#!). Я объяснил их далее [вниз] (http://stackoverflow.com/a/8945888/54396). @ Zombies, метод classloader работает только тогда, когда вам не нужно импортировать классы из этого .jar. Импорты разрешаются до запуска скрипта и импорта .jar – Patrick 2012-01-20 18:10:51
То же самое, как если бы в Java.
Это пример запуска сценария мониторинга состояния MySQL. mysql.jar содержит соединитель MySQL, который я вызываю из status status.groovy.
заводной -cp mysql.jar status.groovy ct1
Вы можете добавить банки в $ HOME/.groovy/Библиотека
Вы также можете попробовать Groovy Grape. Он позволяет использовать аннотации для изменения пути к классам. Его экспериментальный прямо сейчас, но довольно круто. См. docs.groovy-lang.org/.../grape
Запуск оригинального скрипта с #!/usr/bin/env groovy
имеет очень важное ограничение - Никакие дополнительные аргументы не могут быть добавлены. Путь classpath не может быть настроен, без выполнения groovy с параметрами или в отладке. Это не groovy вопроса, но ограничение в том, как работает притон (#!
) - все дополнительные аргументы рассматриваются в качестве единственного аргумента, так #!/usr/bin/env groovy -d
говорит /usr/bin/env
запустить команду groovy -d
Rathen затем groovy
с аргументом d
.
Существует обходной путь для проблемы, который включает в себя загрузку groovy с bash в groovy script.
#!/bin/bash
//usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" [email protected]; exit $?
import org.springframework.class.from.jar
//other groovy code
println 'Hello'
Всякая магия происходит в первых двух строках. Первая строка говорит нам, что это скрипт bash
. bash
начинает работать и видит первую строку. В bash
#
предназначен для комментариев, а //
свернут до /
, который является корневым каталогом. Таким образом, bash
будет запускать /usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" [email protected]
, который начинает разбираться со всеми нашими желаемыми аргументами. "$0"
- это путь к нашему скрипту, и [email protected]
являются аргументами. Теперь groovy работает, и он игнорирует первые две строки и видит наш отличный скрипт, а затем выходит на bash
. bash
затем завершает (exit $?1
) со статусным кодом от groovy.
Мой любимый способ сделать это с Groovy Grapes. Они получают доступ к центральному репозиторию Maven, загружают упоминаемую банку и затем помещают ее в путь к классам. Затем вы можете использовать библиотеку, как и любую другую библиотеку. Синтаксис очень прост:
@Grab(group='com.google.collections', module='google-collections', version='1.0')
Вы можете прочитать более подробную информацию here. Одним из основных преимуществ здесь является то, что вам не нужно распространять свои зависимости при распространении своего сценария. Единственным недостатком этого метода является то, что Jar должен находиться в репозитории Maven.
Добавляя к @Patrick свой ответ, который мне очень помог, я недавно обнаружил еще один трюк.
Если вы добавите много кувшинов в путь к классам на одной линии, все может стать совсем нечитаемым.Но вы можете сделать следующее!
#!/bin/bash
//bin/true && OPTS="-cp blah.jar -Dmyopt=value"
//bin/true && OPTS="$OPTS -Dmoreopts=value2"
//usr/bin/env groovy $OPTS "$0" [email protected]; exit $?
println "inside my groovy script"
Пусть ваши фантазии о том, как комплекс командной строки вы можете разбить этот путь на управляемые части
Maarten
Ниже сочетание Patrick's solution, Maarteen Boekhold's solution и комментарий foozbar, что работает как с Linux и Cygwin:
#!/bin/bash
// 2>/dev/null; SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
// 2>/dev/null; OPTS="-cp $SCRIPT_DIR/lib/extra.jar:$SCRIPT_DIR/lib/spring.jar"
// 2>/dev/null; OPTS="$OPTS -d"
// 2>/dev/null; OPTS="$OPTS -Dlog4j.configuration=file:/etc/myapp/log4j.xml"
// 2>/dev/null; exec groovy $OPTS "$0" "[email protected]"; exit $?
import org.springframework.class.from.jar
//other groovy code
println 'Hello'
Как это работает:
//
является достоверным замечательным комментарием, поэтому все команды bash игнорируются Groovy.//
вернет ошибку, но выход ошибки перенаправляется на/dev/null
и поэтому не отображается.- bash выполняет команды, следующие за точкой с запятой, даже если предыдущая команда не удалась.
exec
заменяет текущую программу в текущем процессе без использования нового процесса. Таким образом, groovy работает в исходном сценарии процесса (ps
показывает процесс как скрипт, а не исполняемый файл)- Оператор
exit $?
, следующий заexec groovy
, препятствует попыткам bash интерпретировать остальную часть скрипта как скрипт bash, а также сохраняет код возврата из строкового скрипта.
Вышеупомянутый трюк bash более удобен в некоторых случаях, чем the RootLoader trick, потому что вы можете использовать регулярные выражения импорта внутри скрипта. Использование трюка RootLoader заставляет вас загружать все классы с использованием отражения. Это нормально в некоторых ситуациях (например, когда вам нужно загрузить драйвер JDBC), но неудобно в других.
Если вы знаете, что ваш скрипт никогда не будет выполнен на Cygwin, то использование решения Patrick или Maarteen, скорее всего, приведет к немного лучшей производительности, поскольку они избегают накладных расходов на создание и выброс ошибки.
Если вы хотите использовать его сразу перед import
деклараций можно как этот :):
// printEmployees.groovy
this.class.classLoader.rootLoader.addURL(
new URL("file:///C:/app/Dustin/product/11.1.0/db_1/jdbc/lib/ojdbc6.jar"))
import groovy.sql.Sql
sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:orcl", "hr", "hr",
"oracle.jdbc.pool.OracleDataSource")
sql.eachRow("SELECT employee_id, last_name, first_name FROM employees")
{
println "The employee's name is ${it.first_name} ${it.last_name}."
}
Взятые из этого javaworld.com article.
Похоже, это уже было задано: http://stackoverflow.com/questions/254385/how-do-i-auto-load-a-database-jar-in-groovy-without-using-the-cp- switch – timdisney 2008-11-20 17:45:42