说明:
(1) 本篇博客主要阐述以下的内容:在【Spring Boot电商项目66:上线部署四:把项目部署到服务器;】中,我们在部署项目的时候,使用到了很多命令;这儿对其中使用到的命令,作进一步的详细介绍和分析;
(2)声明: 本篇博客的内容,没必要全部记忆,以能解决目前的疑问为主要目的;
(3) 本篇博客参考的文章有:
●【Linux scp命令】;
●【[3. lsof 一切皆文件](https://linuxtools- rst.readthedocs.io/zh_CN/latest/tool/lsof.html “3. lsof 一切皆文件”)】;
●【Linux nohup 命令】;
●【[linux 启动后台服务 nohup
/dev/null](https://blog.csdn.net/ahjxhy2010/article/details/51177327 “linux 启动后台服务 nohup >/dev/null”)】;
(4) 声明:本篇博客可能存在理解存在偏差、缺失甚至错误的地方;但目前,该篇博客能够帮助自己形成自洽;
目录
一:上传文件:scp命令;
二:查看当前系统文件:lsof命令;
三:启动Spring Boot项目的jar,也就是启动Spring Boot项目;
1.java -jar:启动jar包;
2.-Dserver.port=8083:启动时,设置端口号;
3.-Dspring.profiles.active=***:选择配置文件;
4.nohup:以后台的方式,执行某个命令;
(1)第一篇参考博客;
(2)第二篇参考博客; (PS:这儿的理解,可能不太准确;)
5.这儿使用到的启动命令解释;(本篇博客的输出结果)
一:上传文件:scp命令;
我们在 【Spring Boot电商项目66:上线部署四:把项目部署到服务器;】中,是通过Windows的cmd控制台,利用scp命令,向服务器上传文件;
scp -r C:\Users\dell\Desktop\images\. root@4**.***.***.**1:/root/images/
以下内容,参考自【Linux scp命令】;
Linux scp命令 用于在Linux下进行远程拷贝文件的命令,和它类似的命令有[cp](https://www.coonote.com/linux/linux-cmd- cp.html “cp”),不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读read only system时,用scp可以帮你把文件移出来。另外,scp还非常不占资源,不会提高多少系统负荷,在这一点上,[rsync](https://www.coonote.com/linux/linux- cmd-rsync.html “rsync”)就远远不及它了。虽然 rsync比scp会快一点,但当小文件众多的情况下,rsync会导致硬盘I/O非常高,而scp基本不影响系统正常使用。
语法
scp (选项) (参数)
选项
-1:使用ssh协议版本1; -2:使用ssh协议版本2; -4:使用ipv4; -6:使用ipv6; -B:以批处理模式运行; -C:使用压缩; -F:指定ssh配置文件; -l:指定宽带限制; -o:指定使用的ssh选项; -P:指定远程主机的端口号; -p:保留文件的最后修改时间,最后访问时间和权限模式; -q:不显示复制进度; -r:以递归方式复制。
参数
- 源文件:指定要复制的源文件。
- 目标文件:目标文件。格式为user@host:filename(文件名为目标文件的名称)。
实例
从远程复制到本地的scp命令与上面的命令雷同,只要将从本地复制到远程的命令后面2个参数互换顺序就行了。
(1)从远处复制文件到本地目录
scp [email protected]:/opt/soft/nginx-0.5.38.tar.gz /opt/soft/
从10.10.10.10机器上的
/opt/soft/
的目录中下载nginx-0.5.38.tar.gz 文件到本地/opt/soft/
目录中。(2)从远处复制到本地
scp -r [email protected]:/opt/soft/mongodb /opt/soft/
从10.10.10.10机器上的
/opt/soft/
中下载mongodb目录到本地的/opt/soft/
目录来。(3)上传本地文件到远程机器指定目录
scp /opt/soft/nginx-0.5.38.tar.gz [email protected]:/opt/soft/scptest
复制本地/opt/soft/目录下的文件nginx-0.5.38.tar.gz到远程机器10.10.10.10的
opt/soft/scptest
目录。(4)上传本地目录到远程机器指定目录
scp -r /opt/soft/mongodb [email protected]:/opt/soft/scptest
上传本地目录
/opt/soft/mongodb
到远程机器10.10.10.10上/opt/soft/scptest
的目录中去。
二:查看当前系统文件:lsof命令;
我们在 【Spring Boot电商项目66:上线部署四:把项目部署到服务器;】中,是通过【lsof -i:端口号】命令,查看某端口号,是否有应用占用:
以下内容参考自【[3. lsof 一切皆文件](https://linuxtools- rst.readthedocs.io/zh_CN/latest/tool/lsof.html “3. lsof 一切皆文件”)】;
3. lsof 一切皆文件
lsof(list open files)是一个查看当前系统文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,该文件描述符提供了大量关于这个应用程序本身的信息。
lsof打开的文件可以是:
- 普通文件
- 目录
- 网络文件系统的文件
- 字符或设备文件
- (函数)共享库
- 管道,命名管道
- 符号链接
- 网络文件(例如:NFS file、网络socket,unix域名socket)
- 还有其它类型的文件,等等
3.1. 命令参数
- -a 列出打开文件存在的进程
- -c<进程名> 列出指定进程所打开的文件
- -g 列出GID号进程详情
- -d<文件号> 列出占用该文件号的进程
- +d<目录> 列出目录下被打开的文件
- +D<目录> 递归列出目录下被打开的文件
- -n<目录> 列出使用NFS的文件
- -i<条件> 列出符合条件的进程。(4、6、协议、:端口、 @ip )( PS:查看指定端口号的进程,正是我们这儿遇到的情况 )
- -p<进程号> 列出指定进程号所打开的文件
- -u 列出UID号进程详情
- -h 显示帮助信息
- -v 显示版本信息
3.2. 使用实例
(1)案例1: 无任何参数;
$lsof| more COMMAND PID USER FD TYPE DEVICE SIZE/OFF
NODE NAME init 1 root cwd DIR 253,0 4096 2 / init 1 root rtd DIR 253,0 4096 2 / init 1 root txt REG 253,0 150352 1310795 /sbin/init init 1 root mem REG 253,0 65928 5505054 /lib64/libnss_files-2.12.so init 1 root mem REG 253,0 1918016 5521405 /lib64/libc-2.12.so init 1 root mem REG 253,0 93224 5521440 /lib64/libgcc_s-4.4.6-20120305.so.1 init 1 root mem REG 253,0 47064 5521407 /lib64/librt-2.12.so init 1 root mem REG 253,0 145720 5521406 /lib64/libpthread-2.12.so
说明:
lsof输出各列信息的意义如下:
COMMAND:进程的名称
PID:进程标识符
PPID:父进程标识符(需要指定-R参数)
USER:进程所有者
PGID:进程所属组
FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等:
(1)cwd:表示current work dirctory,即:应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改 (2)txt :该类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序 (3)lnn:library references (AIX); (4)er:FD information error (see NAME column); (5)jld:jail directory (FreeBSD); (6)ltx:shared library text (code and data); (7)mxx :hex memory-mapped type number xx. (8)m86:DOS Merge mapped file; (9)mem:memory-mapped file; (10)mmap:memory-mapped device; (11)pd:parent directory; (12)rtd:root directory; (13)tr:kernel trace file (OpenBSD); (14)v86 VP/ix mapped file; (15)0:表示标准输入 (16)1:表示标准输出 (17)2:表示标准错误 一般在标准输出、标准错误、标准输入后还跟着文件状态模式:r、w、u等 (1)u:表示该文件被打开并处于读取/写入模式 (2)r:表示该文件被打开并处于只读模式 (3)w:表示该文件被打开并处于 (4)空格:表示该文件的状态模式为unknow,且没有锁定 (5)-:表示该文件的状态模式为unknow,且被锁定 同时在文件状态模式后面,还跟着相关的锁 (1)N:for a Solaris NFS lock of unknown type; (2)r:for read lock on part of the file; (3)R:for a read lock on the entire file; (4)w:for a write lock on part of the file;(文件的部分写锁) (5)W:for a write lock on the entire file;(整个文件的写锁) (6)u:for a read and write lock of any length; (7)U:for a lock of unknown type; (8)x:for an SCO OpenServer Xenix lock on part of the file; (9)X:for an SCO OpenServer Xenix lock on the entire file; (10)space:if there is no lock.
TYPE:文件类型,如DIR、REG等,常见的文件类型:
(1)DIR:表示目录 (2)CHR:表示字符类型 (3)BLK:块设备类型 (4)UNIX: UNIX 域套接字 (5)FIFO:先进先出 (FIFO) 队列 (6)IPv4:网际协议 (IP) 套接字
DEVICE:指定磁盘的名称
SIZE:文件的大小
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称
(2)案例2: 查找某个文件相关的进程;
$lsof /bin/bash COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld_sa 2169 root txt REG 253,0 938736 4587562 /bin/bash ksmtuned 2334 root txt REG 253,0 938736 4587562 /bin/bash bash 20121 root txt REG 253,0 938736 4587562 /bin/bash
(3)案例3: 列出某个用户打开的文件信息;
$lsof -u username -u 选项,u是user的缩写
(4)案例4: 列出某个程序进程所打开的文件信息;
$lsof -c mysql
(5)案例5: 列出某个用户以及某个进程所打开的文件信息;
$lsof -u test -c mysql
(6)案例6: 通过某个进程号显示该进程打开的文件;
$lsof -p 11968
(7)案例7: 列出所有的网络连接;
$lsof -i
(8)案例8: 列出所有tcp 网络连接信息;
$lsof -i tcp $lsof -n -i tcp COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME svnserve 11552 weber 3u IPv4 3799399 0t0 TCP *:svn (LISTEN) redis-ser 25501 weber 4u IPv4 113150 0t0 TCP 127.0.0.1:6379
(LISTEN)
(9)案例9: 列出谁在使用某个端口;( PS:查看指定端口号的进程,正是我们这儿遇到的情况 )
$lsof -i :3306
(10)案例10: 列出某个用户的所有活跃的网络端口;
$lsof -a -u test -i
(11)案例11: 根据文件描述列出对应的文件信息;
$lsof -d description(like 2)
示例:
$lsof -d 3 | grep PARSER1 tail 6499 tde 3r REG 253,3 4514722 417798
/opt/applog/open/log/HOSTPARSER1_ERROR_141217.log.001
说明: 0表示标准输入,1表示标准输出,2表示标准错误,从而可知:所以大多数应用程序所打开的文件的 FD 都是从 3 开始;
(12)案例12: 列出被进程号为1234的进程所打开的所有IPV4 network files;
$lsof -i 4 -a -p 1234
(13)案例13: 列出目前连接主机nf5260i5-td上端口为:20,21,80相关的所有文件信息,且每隔3秒重复执行;
lsof -i @nf5260i5-td:20,21,80 -r 3
三:启动Spring Boot项目的jar,也就是启动Spring Boot项目;
我们在 【Spring Boot电商项目66:上线部署四:把项目部署到服务器;】中,我们是通过【java -jar】命令,启动我们的Spring Boot项目;
nohup java -jar -Dserver.port=8083 -Dspring.profiles.active=prod
/root/mall-0.0.1-SNAPSHOT.jar > /root/null 2>&1 &
其中,使用到了nohup、java -jar等;我们需要详细分析一下;
1.java -jar:启动jar包;
参考自【java -jar 和 -cp详解】,该文的作者是【叫我阿柒啊2021】;
声明:(1)这篇博客中,遇到不是特别清楚的也没事;目前来说,能够说明【java -jar】命令,是启动jar包的,就足够了;(2)【java -jar】主要是启动jar,而其中主要就是:JVM把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被JVM直接使用的Java类型,这就是JVM的类加载过程;;;所以,要想真正的比较透彻的理解这个问题,后续就需要深入了解JVM的有关内容;
前言
今天从知乎上看到了java -jar的问题,想起自己刚学java的时候也迷茫过,java -jar和-cp有什么区别。java -jar怎么靠着一个jar包来运行程序的,于是乎就打算总结一下自己的使用经验。
命令行执行程序
假如我们有一个程序,把它打包成Test.jar,如何运行才能成功输出Hello World;
package com.test; public class Test { public static void main(String[] args) { System.out.println("Hello World"); } }
我们有以下两种方法
1. java -jar Test.jar 2. java -cp com.test.Test Test.jar
(1)方式1:java -jar:
我们解压jar包,META-INF文件夹下都有 MANIFEST.MF ,内容如图:
java -jar就是通过 Main-Class 来找到Test类并执行其中的main(),输出Hello World!如果你的MANIFEST.MF文件中没有Main-Class,就会提示Cant load main- class之类的错误。所以在导出jar包的时候一定要指定main-class。 如图:
(2)方式2:java -cp:
对于java -cp就不需要指定Main- Class来指定入口。因为第一个参数就指定了你的入口类,第二个参数就是你的jar包。它会根据你的jar包找到第一个参数指定的Test类,来输出HelloWorld。
怎么选择
假设我们这个程序的运行需要依赖一个叫Dep.jar的包。 如果我们使用-jar的话,就只能把Dep.jar放到Test.jar中,因为-jar只能指定一个jar包. 如果是使用-cp,我们可以选择将Dep.jar放到Test.jar中,也可以选择使用以下命令来运行:
java -cp com.test.Test Test.jar:Dep.jar
cp其实就是classpath,在linux中多个jar包用 : 分割,代表了程序运行需要的所有jar包。这样就可以不用将所有依赖都放到Test.jar下.这样做的好处就是,假如修改了Test类,只上传修改后的Test.jar到服务器即可,不需要再将所有依赖放到Test.jar中再上传一遍,节约了时间。
言归正传
java -jar执行jar包过程,到底背后有哪些技术步骤:
- 通过MANIFEST.MF中的Main-Class找到入口类,启动程序
- 启动JVM,分配内存(java内存结构和GC知识)
- 根据引用关系加载类(类加载、类加载器、双亲委托机制),初始化静态块等
- 执行程序,在虚拟机栈创建方法栈桢,局部变量等信息
2.-Dserver.port=8083:启动时,设置端口号;
参考自【SpringBoot项目启动指定端口的三种方式】;
SpringBoot 项目 启动指定端口 的三种方式:
方式一:
配置文件中添加server.port=8080
server: port: 8080 ##这儿是yml格式的配置文件啦
方式二:
在命令行中指定启动端口,比如传入参数一server. port=8000
java -jar xxx.jar -- server.port=8000
方式三:
传入虚拟机系统属性-Dserver.port=9000
java -Dserver.port=9000 -jar xxx.jar
3.-Dspring.profiles.active=***:选择配置文件;
设置,启动时,使用哪个配置文件;在【附加:Spring Boot项目:多个配置文件介绍;启动项目时候,怎么选择指定配置文件;】作了一些介绍;
4.nohup:以后台的方式,执行某个命令;
(1)第一篇参考博客;
参考自【Linux nohup 命令】;
(1)nohup简介;
nohup 英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。
nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。
(2)使用权限: 所有使用者;
(3)语法格式:
nohup Command [ Arg … ] [ & ]
(4)参数说明:
Command :要执行的命令。
Arg :一些参数,可以指定输出文件。
& :让命令在后台执行,终端退出后命令仍旧执行。
(5)实例:
以下命令在后台执行 root 目录下的 runoob.sh 脚本:
nohup /root/runoob.sh &
在终端如果看到以下输出说明运行成功:
appending output to nohup.out
这时我们打开 root 目录 可以看到生成了 nohup.out 文件。
如果要停止运行,你需要使用以下命令查找到 nohup 运行脚本到 PID,然后使用 kill 命令来删除:
ps -aux | grep "runoob.sh"
参数说明:
- a : 显示所有程序
- u : 以用户为主的格式来显示
- x : 显示所有程序,不区分终端机
另外也可以使用 ps -def | grep “runoob.sh” 命令来查找。
找到 PID 后,就可以使用 kill PID 来删除。
kill -9 进程号PID
以下命令在后台执行 root 目录下的 runoob.sh 脚本,并重定向输入到 runoob.log 文件:
nohup /root/runoob.sh > runoob.log 2>&1 &
2 >&1 解释:
将标准错误 2 重定向到标准输出 &1 ,标准输出 &1 再被重定向输入到 runoob.log 文件中。
- 0 – stdin (standard input,标准输入)
- 1 – stdout (standard output,标准输出)
- 2 – stderr (standard error,标准错误输出)
(2)第二篇参考博客; (PS:这儿的理解,可能不太准确;)
参考自【[linux 启动后台服务 nohup
/dev/null](https://blog.csdn.net/ahjxhy2010/article/details/51177327 “linux 启动后台服务 nohup >/dev/null”)】;这篇博客并没有仔细看,这儿仅仅是结合其中的内容,总结了以下内容;
(1) 使用nohup+Command的时候,我们可以把被调用程序的输出等信息,输出到文件中去;
(2) nohup命令是后台执行程序,运行程序后,一般会生成文件nohup.out,所有标准输出会写入该文件。在如【nohup java -jar -Dserver.port=8083 -Dspring.profiles.active=prod /root/mall-0.0.1-SNAPSHOT.jar > /root/null 2>&1 &】命令中, 有/root/null,将不会产生任何文件。
(3) 其中,我们可以对输出进行设置;
● 0:标准输入;1:标准输出;2:标准错误信息输出;可以用来指定需要重定向的标准输入或输出。
● 在一般使用时,默认的是标准输出,既1。
● 当我们需要特殊用途时,可以使用其他标号。 例如,将某个程序的错误信息输出到log文件中:./program 2>log。这样标准输出还是在屏幕上,但是错误信息会输出到log文件中。
● 另外,也可以实现0,1,2之间的重定向。例如,2>&1:将错误信息重定向到标准输出。
(4) /dev/null :Linux下还有一个特殊的文件/dev/null,它就像一个无底洞,所有重定向到它的信息都会消失得无影无踪。这一点非常有用,当我们不需要回显程序的所有信息时,就可以将输出重定向到/dev/null。
● 如果想要正常输出和错误信息都不显示,则要把标准输出和标准错误都重定向到/dev/null, 例如:# ls 1 >/dev/null _2
/dev/null_;
● 还有一种做法是将错误重定向到标准输出,然后再重定向到 /dev/null,例如:# ls >/dev/null 2>&1;( PS:这正是,我们在【nohup java -jar -Dserver.port=8083 -Dspring.profiles.active=prod /root/mall-0.0.1-SNAPSHOT.jar > /root/null 2>&1 &】中的做法;)注意:此处的顺序不能更改,否则达不到想要的效果,此时先将标准输出重定向到 /dev/null,然后将标准错误重定向到标准输出,由于标准输出已经重定向到了/dev/null,因此标准错误也会重定向到/dev/null,于是一切静悄悄:-)
(5) nohup 结合/dev/null:由于使用nohup时,会自动将输出写入nohup.out文件中,如果文件很大的话,nohup.out就会不停的增大,这是我们不希望看到的,因此,可以利用/dev/null来解决这个问题;
● nohup ./program >/dev/null 2 >log &;:标准错误信息输出到log,标准输出信息输出到null(也就意味着标准输出直接丢弃)
● nohup ./program >/dev/null 2 >&1 &;:将错误重定向到标准输出,然后再重定向到null,也就意味着标准输出和标准错误信息都丢弃;
● nohup php ./ConsumerX.php >> /dev/null &;:标准输出和标准错误信息都不显示;
● nohup /usr/local/php-5.6.7/bin/php ./ConsumerX.php >> /root/Consumer/run.log 2 >&1 &:将错误重定向到标准输出,然后再重定向到 run.log,也就意味着标准输出和标准错误信息都输出到run.log;
5.这儿使用到的启动命令解释;(本篇博客的输出结果)
我们这儿使用的、完整的命令是:
nohup java -jar -Dserver.port=8083 -Dspring.profiles.active=prod
/root/mall-0.0.1-SNAPSHOT.jar > /root/null 2>&1 &
对上面的语句解释如下:
nohup java -jar -Dserver.port=8083 -Dspring.profiles.active=prod /root/mall-0.0.1-SNAPSHOT.jar > /root/null 2 >&1 &
(1)nohup:nohup命令,没什么好说的;
(2)java -jar -Dserver.port=8083 -Dspring.profiles.active=prod /root/mall-0.0.1-SNAPSHOT.jar:将要后台执行的Command命令;
(3)/root/null:Arg参数;在这个过程中,0:标准输入、1:标准输出、2:标准错误信息输出,的,指定输出文件;
(4)2>&1:先将标准输出重定向到 /root/null,然后将标准错误重定向到标准输出,由于标准输出已经重定向到了/root/null,因此标准错误也会重定向到/root/null;
(5)&:让命令在后台执行,终端退出后命令仍旧执行。