【问题标题】:Using an environment variable for java classpath not working within shell script使用 Java 类路径的环境变量在 shell 脚本中不起作用
【发布时间】:2013-07-01 09:40:04
【问题描述】:

我注意到一个反复出现的问题:在 java 命令行在 shell 脚本中上为类路径使用 env var 不起作用。

首先,让我们看看做了什么:两者都在脚本中使用硬编码的类路径,如下所示:(注意:“类路径是”语句打印在 java 程序本身中)

steve@mithril:/shared$     java -classpath .:/shared/mysql-connector-java-5.1.25-bin.jar DbPing com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql user password
classpath is .:/shared/mysql-connector-java-5.1.25-bin.jar
Attempting connection to com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql  password
Connecting to user using URL=jdbc:mysql://localhost:3306/mysql
Successfully connected.

也可以直接在 shell 中使用 env var

steve@mithril:/shared$ export CP=.:/shared/mysql-connector-java-5.1.25-bin.jar
steve@mithril:/shared$ java -classpath $CP DbPing com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql user password 
classpath is .:/shared/mysql-connector-java-5.1.25-bin.jar
Attempting connection to com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql  password
Connecting to user using URL=jdbc:mysql://localhost:3306/mysql
Successfully connected.

*不 * 的作用:在 shell 脚本中运行如上所示的相同命令:

steve@mithril:/shared$ cat dbping.mysql
CP=.:/shared/mysql-connector-java-5.1.25-bin.jar
echo $CP
java -classpath $CP DbPing com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql user password 
#java -classpath .:/shared/mysql-connector-java-5.1.25-bin.jar DbPing com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql user password 

steve@mithril:/shared$  ./dbping.mysql
.:/shared/mysql-connector-java-5.1.25-bin.jar
classpath is .:/shared/mysql-connector-java-5.1.25-bin.jar
Attempting connection to com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mysql  password
Could not load db driver com.mysql.jdbc.Driver
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:190)
    at DbPing.getConnection(DbPing.java:34)
    at DbPing.main(DbPing.java:22)
Exception in thread "main" java.sql.SQLException: com.mysql.jdbc.Driver
    at DbPing.getConnection(DbPing.java:41)
    at DbPing.main(DbPing.java:22)

跟进:脚本中包含 windows 样式的换行符。显然 \r 破坏了内部环境变量。发现这个使用

  od -cx

。无论如何,我还是要感谢 stephen c,因为他的鼓励让我走上了寻找解决方案的正确轨道

【问题讨论】:

  • 我检查了一些我坐在那里的脚本,并引用了我的类路径参数,尽管我有一个 glob。出于好奇,您是否得到与 java -classpath "$CP" DbPing... 相同的结果?
  • 什么会打印classpath is ... 消息?标准的java 应用程序启动器不这样做。

标签: java shell classpath


【解决方案1】:

您描述的症状相当令人费解。我看不到问题(脚本看起来正确),但我知道如何开始追踪它。

  1. 去掉脚本中被注释掉的行。

  2. #!/bin/sh 行添加到脚本的开头,以确保您实际上使用正确的shell 来执行它。 (这样做总是一个好主意......即使您认为默认情况下会获得正确的 shell。这可能会改变,具体取决于平台。)

  3. 要弄清楚 shell 在做什么,请在 #!/bin/sh 行之后添加 set -vx

“-v”表示回显每个读取的脚本行,“-x”表示回显实际执行的命令行。这将准确地告诉您正在运行哪些命令...以便您弄清楚命令参数真正是什么。

【讨论】:

  • “classpath is”语句是在 java DbPing 程序本身中生成的。我使用的是 ubuntu,所以 /bin/sh 与 /bin/bash 相同,但无论如何我都会添加 -vx
  • @javadba - 你应该总是放一个#!任何脚本上的行。 1) 文件。 2)您的脚本将来可能需要在另一个平台上运行,并且您使用不同的 shell 可能很重要。 3) AFAIK 在“/bin/sh”和“/bin/bash”之间存在行为差异,即使它们是相同的可执行文件......
  • 我发现问题出在 Windows 样式的换行符上。但我给了你答案,因为它帮助我用细齿梳子更仔细地观察剧本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 2023-03-05
  • 2023-03-24
  • 2019-05-02
  • 2012-02-15
  • 1970-01-01
相关资源
最近更新 更多