来源:https://blog.csdn.net/coolcooldool/article/details/51775105

最近一个项目需要写一个batch定时读取文件往数据库里插入记录,第一次写,遇到好多问题,记录一下。

先从shell如何调用java说起

建立如下目录结构

batch                          根目录
├── bin                    shell放置目录(如果直接放java class也放这里)
│   ├── 1.sh
│   ├── test.sh
│   └── startup.sh
├── libs                   引用jar包放置目录
│   ├── commons-io-2.4.jar
│   ├── commons-lang3-3.3.2.jar
│   ├── ini4j-0.5.4.jar
│   ├── junit-3.8.1.jar
│   ├── log4j-1.2.17.jar
│   ├── postgresql-9.3-1102-jdbc41.jar
│   └── myjar.jar   自己的jar
├── lock                 锁文件(空文件)
└── logs                 程序log目录
    ├── cron.log
    └── myjar.log

然后是shell脚本

startup.sh

[cpp] view plaincopy
  1. #!/bin/sh
  2. echo ""
  3. echo "----------------------------------"
  4. echo "start at `date '+%Y-%m-%d %H:%M:%S'` ..."
  5. JAVA_HOME=/usr/java/jdk1.8.0_45
  6. MAIN_CLASS=com.superbatch.batch.DetectLogBatch
  7. SH_DIR=/usr/local/ee4one_batch/bin
  8. cd $SH_DIR
  9. dir="."
  10. temp=""
  11. libs="../libs/*"
  12. append(){
  13. temp=$temp":"$1
  14. }
  15. for file in $libs
  16. do
  17. append $file
  18. done
  19. export CLASSPATH=$dir:../$temp
  20. echo $CLASSPATH
  21. #nohup
  22. ${JAVA_HOME}/bin/java -classpath ${CLASSPATH} ${MAIN_CLASS}
  23. echo "finished at `date '+%Y-%m-%d %H:%M:%S'` ..."
  24. exit 0

第1行声明shell类型

2-4行输出一些时间信息

6-8行分别定义了一些变量后面会用到

10行让程序进入到自己shell脚本的bin目录,如果使用cron执行这很重要,因为libs文件夹定义的是相对路径,而cron的默认执行路径则找不到,如果手工进入到bin目录下执行则无所谓

11-24行只做了一件事情,就是将bin目录,batch目录,libs目录下的所有jar包,全部加入到classpath中,生成一长串字符串如下:

[plain] view plaincopy
  1. .:../:../libs/commons-io-2.4.jar:../libs/commons-lang3-3.3.2.jar:../libs/ini4j-0.5.4.jar:../libs/junit-3.8.1.jar:../libs/log4j-1.2.17.jar:../libs/postgresql-9.3-1102-jdbc41.jar:../libs/myjar.jar

只不过是用了一个append()方法和一个for循环实现了字符串的拼接,如果jar包不多的话手工写上去也是完全可以的。

26行打印了一下生成的$CLASSPATH变量的值

29行是真正的调用java执行main()方法,要说的是 在前面如果加上“nohup ”的话,java的执行log就会直接输出到当前目录下的nohup.log文件里。如果是手工执行在最后加上“ $”的话程序将会后台执行,也就是说关闭命令行窗口并不会中断程序的执行,不过这种方法中shell的进程并不会等待java方法执行完成,而是立即完成。

-classpath 后面的$CLASSPATH是告诉java去什么地方找到用到的jar包,我的程序是导出的jar包,我也同样把我的jar包放入到了这个目录就可以了,如果是编译的class文件的话放到bin目录下也可以。

32行输出log

33行程序正常退出

如果是手工通过shell调用java那以上文字就已经搞定了

下面说如何通过crontab调用shell

在命令行下输入

[plain] view plaincopy
  1. crontab -e

可以打开cron任务的编辑界面

注意的是cron是区分用户的,每个用户的cron是单独的

[plain] view plaincopy
  1. */1 * * * * /usr/local/batch/bin/startup.sh

这样写的话就是每分钟执行一次指定的shell了

前面的几个* 分别是minute(分),hour(小时),day of month(日期),month(月份), day of week(星期),具体的可以查询一下

这个只是每分钟执行一次,下面的命令可以将执行的log输入到指定文件也就是shell中的echo

[plain] view plaincopy
  1. */1 * * * * /usr/local/batch/bin/startup.sh >>/usr/local/batch/logs/cron.log

但是有好多时候,比如我的需求,如果数据量过大,上一个batch还没执行完则不希望下一个batch也执行,本次不执行就可以了这个需求可以通过flock来实现

[plain] view plaincopy
  1. */1 * * * *  flock -xw 10 /usr/local/ee4one_batch/lock -c "sh /usr/local/ee4one_batch/bin/test.sh >> /usr/local/ee4one_batch/logs/cron.l

上面的命令前面就是用flock命令去给一个文件上锁,这个锁是一个全局锁如果其它命令也来获取这个文件的锁的而获取不到的话则不会被执行,这个锁文件是什么文件无所谓。

后面的参数是获取一个独占锁,如果获取不到,则等待10秒钟

-s,--shared:   获得一个共享锁
-x,--exclusive:获得一个独占锁
-u,--unlock:   移除一个锁,通常是不需要的,脚本执行完会自动丢弃锁
-n,--nonblock: 如果没有立即获得锁,直接失败而不是等待
-w,--timeout:  如果没有立即获得锁,等待指定时间
-o,--close:    在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控
-c,--command:  在shell中运行一个单独的命令
-h,--help      显示帮助
-V,--version:  显示版本

一些参数贴出来

这样,通过crontab,调用shell,实现java main()方法的定期执行,并且防止同一时间重复执行就完成了。

这样做的好处是不用通过java来判断多重执行,java判断起来也不是很方便。

有一些小补充。

1,shell里面进入目录的那句话很重要,因为这个找了好久的原因。

2,执行shell的时候可以用sh -x startup.sh来执行输出详细执行log。

3,cron的执行log在/var/log/cron文件里面,可以查看执行详细。

4,我的java程序log是自己用log4j出力到logs下面的。

【Linux】shell调用Java程序main方法通过crontab定时执行相关推荐

  1. 在JAVA语言程序中main_在Java程序main方法中,正确的参数是

    [单选题]下列叙述中,错误的是 [填空题]Access属于()数据库,Access中,不允许在主关键字字段中有重复值或(). [单选题]如下哪些字符串是Java中的标识符? [填空题]常用的基本电量传 ...

  2. LINUX中运行java程序的方法

    要想在linux中运行java的项目需要先将项目打包成war包或者jar包. 其中打包成war包需要将war包部署到tomcat服务器上才能运行.而打包成jar包可以直接使用java命令执行. 在li ...

  3. qt调用Linux脚本范例,QT下实现对Linux Shell调用的几种方法

    使用QProcess QThread ============================================ #include int main() { QProcess::exec ...

  4. qtp启动java程序_转: QTP六脉神剑之调用Java程序

    查看( 1147 ) / 评论( 21 ) 六脉神剑之调用程 序0Xp1zLN_0版权声明:原创作品,转载请以链接方式注明出自http://www.51testing.com/?35,否则将追究法律责 ...

  5. qtp启动java程序_QTP六脉神剑之调用Java程序

    版权声明:原创作品,转载请以链接方式注明出自,否则将追究法律责任.本文出自songfun的51Testing软件博客:不少网友对于QTP调用Java程序感到束手无策,实际上要调用Java程序是非常容易 ...

  6. eclipse java调用c 代码吗_linux下通过eclipse开发用java调用c程序的方法

    linux下通过eclipse开发用java调用c程序的方法: 1.先建立好java工程并建立java文件如下: public class testso {     static {         ...

  7. java进程里面调用方法_在java里面调用CUI程序的方法

    在java里面调用CUI程序的方法推荐查看本文HTML版本 在java里面调用CUI程序的方法 问题描述: 该函数在win平台上面调用不是很成功,GUI会可以调出来,但可能和屏蔽调其中的一些用 ...

  8. Java调用C++程序实现方法

    Java调用C++程序实现方法(1) 这篇博文是自己在学习过程中,踩了很多坑之后,为了避免广大热爱编程的盆友再像我这样浪费太多时间,索性将自己的实现方法总结出来,以供大家参考.程序最终实现的是Hell ...

  9. Java不用main方法运行_如何在不定义main方法的情况下运行Java程序?

    我正在查看一些Java源代码,并注意到main方法没有定义. Java如何编译源代码而不知道从哪里开始? main方法仅在Java虚拟机执行代码时使用.没有main方法就无法执行代码,但仍然可以编译代 ...

最新文章

  1. Android中Context 的理解
  2. table 锁定表头
  3. jvm性能调优实战 - 48无限循环调用和没有缓存的动态代理引起的OOM
  4. python计算圆周率_用python计算圆周率Π
  5. 如何从零学习Python----知乎答案
  6. 上海服务器虚拟机系统,服务器虚拟机系统重装系统
  7. Shell定时删除日志
  8. Oracle数据库的四款工具软件
  9. html跳转按钮谷歌浏览器点击没反应,网页打印的按钮无效,点击打印没有任何反映!求解!...
  10. 如何用cocos2d-x来开发简单的Uphone游戏:(一) 下载安装和HelloWorld
  11. 淘宝官方订单API接口,商品分类属性
  12. 【防火墙_策略路由】
  13. BurpSuite系列(十)----Extender模块(扩展器)
  14. 【Apache Shiro 身份认证绕过漏洞 (CVE-2022-32532)-漏洞复现实战——关注紫灵小姐姐不踩坑】
  15. 【小白学Java】D20》》》Iterator迭代器 增强for循环
  16. 15个值得推荐的个人提升方法
  17. 设置共享文件夹之Mac技巧
  18. 活动回顾|ShardingSphere X openGauss,将会产生怎样的化学反应?
  19. 前后端分离项目的服务器部署
  20. 安卓微信7.0版本的微信支付只支持拉起默认的微信,不支持应用双开的微信

热门文章

  1. Project: 项目经理新建资源预订
  2. 微软已停止对Vista RTM(SP0)的服务支持
  3. enter 默认搜索
  4. mac上远程连接windows
  5. 每日英语:Do Bicycle Helmet Laws Really Make Riders Safer?
  6. 谷歌Chrome 紧急修复已遭利用的两个0day
  7. 速修复!OpenSSL 披露DoS 和证书验证高危漏洞,可导致服务器崩溃
  8. VMware 修复 Fusion 和 Horizon 中的两个提权漏洞
  9. 出于安全考虑,谷歌禁用三款 Linux web 浏览器登录其服务
  10. 如果外卖APP想窃听我,有几个骚操作?