M - Find a way

本文介绍了一种使用双向BFS算法解决迷宫中两个角色寻找相遇点的问题。通过分别从两个起点进行广度优先搜索,并记录可达路径长度,最终找到两者相遇所需的最短步数。此算法适用于解决含有障碍物的地图上寻找最短路径问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


记下两人坐标同时BFS即可,注意有的KCF可能到不了的情况


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
using namespace std;
int m,n,vis[210][210],t[210][210],t1[210][210];
char a[210][210];
struct point
{
    int x;
    int y;
}po[4];
queue<point>q;

void BFS1()
{
    int x,y,i;
    while(!q.empty())
    {
        po[3]=q.front();q.pop();
        x=po[3].x;y=po[3].y;i=t1[y][x];
        x++;
        if(x<=n&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t1[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        x-=2;
        if(x>=1&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t1[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        x++;y++;
        if(y<=m&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t1[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        y-=2;
        if(y>=1&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t1[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
    }
    return;
}

void BFS2()
{
    int x,y,i;
    while(!q.empty())
    {
        po[3]=q.front();q.pop();
        x=po[3].x;y=po[3].y;i=t[y][x];
        x++;
        if(x<=n&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        x-=2;
        if(x>=1&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        x++;y++;
        if(y<=m&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
        y-=2;
        if(y>=1&&vis[y][x]==0&&(a[y][x]=='.'||a[y][x]=='@'))
            {vis[y][x]=1;t[y][x]=i+1;po[3].x=x;po[3].y=y;q.push(po[3]);}
    }
    return;
}

int main()
{
    int i,j,s;
    while(~scanf("%d %d",&m,&n))
    {
        s=100000;memset(t,0,sizeof(t));memset(t1,0,sizeof(t1));
        if(m==0&&n==0) break;
        for(j=1;j<=m;j++)
        {
            getchar();
            for(i=1;i<=n;i++)
            {
                scanf("%c",&a[j][i]);
                if(a[j][i]=='Y') {po[1].x=i;po[1].y=j;}
                if(a[j][i]=='M') {po[2].x=i;po[2].y=j;}
            }
        }
        memset(vis,0,sizeof(vis));
        q.push(po[1]);vis[po[1].y][po[1].x]=1;BFS1();
        memset(vis,0,sizeof(vis));
        q.push(po[2]);vis[po[2].y][po[2].x]=1;BFS2();
        for(j=1;j<=m;j++)
            for(i=1;i<=n;i++) if(a[j][i]=='@'&&t[j][i]+t1[j][i]<s&&t[j][i]!=0&&t1[j][i]!=0) s=t[j][i]+t1[j][i];
        printf("%d\n",s*11);
    }
    return 0;
}

#!/bin/bash #source ~/.bashrc source /etc/profile #本文作用:当前目录下所有jar的启动-重启-停止-findall等操作 #tset.sh stop -a (如果该JAR包已启动则先杀后启) #主要指令 分为 start(启动) stop(停止) 如果没写 则默认start #次要指令 -x {纯数字} (非必填) 设置JVM -a 启动当前文件夹下所有jar包(非必填) #方式1已验证成功 ./test123.sh startfile/stopfile/restartfile/ 根据事先写好的test1111.sh内容进行启动 #方式2已验证成功 ./test123.sh startall/stopall/restartall/ 根据当前路径下所有jar包进行启动 #命令3已验证成功 ./test123.sh c8085.jar(如果没起就起,如果已起就重启) #命令4已验证成功 ./test123.sh findall(查找出当前目录下所有*.jar格式的包) #备注:需要将di2lie里边的grep -v test123 改成启动文件名。 #test.sh {主要指令} echo "启动qidong" # 1启动 2停止 3重启 export JVM_XM="-Xms256 -Xmx256" export JAR_NAMES export JAR_PID #export java_path=`echo $JAVA_HOME` java_path=$(dirname $(dirname $(readlink -f $(which javac)))) #export java_path=`/home/jdk1.8.0_281` export pids=`ps -ef | grep $* | grep -v grep | awk '{print $2}'| xargs` export di1lie=`ps -ef | grep $* | grep -v 'grep' | awk '{print $1}' | xargs` export di2lie=`ps -ef | grep $* | grep -v "grep" | grep -v start123 | awk '{print $2}' | xargs` ##export aaa=($(find . -type f -name "*.jar" |sed 's#^\./##' |grep -v "/")) #当前文件夹下所有jar,暂时不用,但aaa的结果是对的 export FILE_NAME=($(find *.jar | awk '{print $1 ""}')) #当前文件夹所有jar export java_id=$(ps -ef|grep java |grep -v grep |awk '{print $2}') #-x 设置JVM 暂时未实现 #-a 启动当前文件夹全部jar包 已实现 ./test123.sh startall for arg in $*; do case $arg in #方式1 "startfile") #JAR_NAMES[${#JAR_NAMES[@]}]=$arg echo "startfile";; "stopfile") #JAR_NAMES[${#JAR_NAMES[@]}]=$arg echo "stopfile";; "restartfile") #JAR_NAMES[${#JAR_NAMES[@]}]=$arg echo "restartfile";; #方式2 "startall") #JAR_NAMES[${#JAR_NAMES[@]}]=$FILE_NAME echo "startall";; "stopall") #JAR_NAMES[${#JAR_NAMES[@]}]=$FILE_NAME echo "stopall";; "restartall") #JAR_NAMES[${#JAR_NAMES[@]}]=$FILE_NAME echo "restartall";; #命令3 *".jar") #JAR_NAMES[${#JAR_NAMES[@]}]=$arg echo ".jar";; #命令4 "findall") #JAR_NAMES[${#JAR_NAMES[@]}]=$FILE_NAME echo "findall";; esac done for name in ${JAR_NAMES[*]} do #$pids=`ps -ef | grep java | grep -v "grep" | awk '{print $2}'` # echo "${JAR_NAMES[*]} 000000000000000000" echo "000000000000000000" done for pid in $arg do case $arg in #方式1 "startfile") . ./test1111.sh #JAR_PID[${#JAR_PID[@]}]=`ps -ef | grep java | grep -v grep | awk '{print $2}' | xargs` pids=`ps -ef | grep java | grep -v "grep" | awk '{print $2}'` ;; "stopfile") pids=`ps -ef | grep java | grep -v "grep" | awk '{print $2}'` kill -9 $pids;; #JAR_PID[${#JAR_PID[@]}]=`ps -ef | grep java | grep -v grep | awk '{print $2}' | xargs` #kill -9 $JAR_PID;; "restartfile") pids=`ps -ef | grep java | grep -v "grep" | awk '{print $2}'` kill -9 $pids . ./test1111.sh;; #方式2 "startall") for i in ${!FILE_NAME[*]}; do jar_id=`(ps -ef | grep ${FILE_NAME[i]} | grep -v "grep" | grep -v start123 | awk '{print $2}' | xargs )` #进程 if [[ ( ${FILE_NAME[i]} == *"-comprehensive.jar"*) ]]; then #comprehensive包 if [[ ( $jar_id != "" ) ]]; then #起了就不起 echo "${FILE_NAME[i]} is already started! the process is $jar_id/" fi if [[ ( $jar_id == "" ) ]]; then #没起就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms1500M -Xmx1500M -jar "${FILE_NAME[i]}" > "${FILE_NAME[i]}.log" 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi elif [[ ( ${FILE_NAME[i]} == *"-auc.jar"*) ]]; then #auc包 if [[ ( $jar_id != "" ) ]]; then #起了就不起 echo "${FILE_NAME[i]} is already started,the process is $jar_id/" fi if [[ ( $jar_id == "" ) ]]; then #没起就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar "${FILE_NAME[i]}" > "${FILE_NAME[i]}.log" 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi else if [[ ( $jar_id != "" ) ]]; then #起了就不起 echo "${FILE_NAME[i]} is already started,the process is $jar_id/" fi if [[ ( $jar_id == "" ) ]]; then #没起就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar "${FILE_NAME[i]}" > "${FILE_NAME[i]}.log" 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi fi printf "\n" done ;; "stopall") abc=$(pwd) #shell脚本里。获取当前路径值赋值给abc echo "pwd:$(pwd)" for id in ${java_id[*]}; do exe_path=$(readlink /proc/$id/cwd) if [[ "$exe_path" == "$abc" ]];then #echo "id=$id~~~~~~~~~~~" kill -9 $id echo "$id is killed" else echo "the process:$id start way is not in $abc ,the way is in $exe_path" fi; done ;; "restartall") abc=$(pwd) #shell脚本里。获取当前路径值赋值给abc for id in ${java_id[*]}; do exe_path=$(readlink /proc/$id/cwd) if [[ "$exe_path" == "$abc" ]];then kill -9 $id echo "$id is killed" else echo "the process:$id start way is not in $abc , the way is in $exe_path" fi; done for i in ${!FILE_NAME[*]}; do if [[ ( ${FILE_NAME[i]} == *"-comprehensive.jar"*) ]]; then #comprehensive包 if [[ ($di1lie=="root root root" )&&( $di2lie != "" )]] ; then #comprehensive起了,先杀再起 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms1500M -Xmx1500M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "$di2lie is start ready!" fi if [[ ( $di1lie == "root root" )&&( $di2lie == "" ) ]]; then #comprehensive没起,就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms1500M -Xmx1500M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi elif [[ ( ${FILE_NAME[i]} == *"-auc.jar"*) ]]; then #auc包 if [[ ($di1lie=="root root root" )&&( $di2lie != "" )]] ; then #auc起了,先杀再起 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "${FILE_NAME[i]} is start ready!" fi if [[ ( $di1lie == "root root" )&&( $di2lie == "" ) ]]; then #auc没起,就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi else #其他包 if [[ ($di1lie=="root root root" )&&( $di2lie != "" ) ]]; then #起了先杀再起111 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "${FILE_NAME[i]} is restart readay!" fi if [[ ( $di1lie == "root root" )&&( $di2lie == "" ) ]]; then #没起就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar $abc/${FILE_NAME[i]} > $abc/${FILE_NAME[i]}.log 2>&1 & echo "${FILE_NAME[i]} is start readay!" fi fi done ;; #命令3 *".jar") abc=$(pwd) if [[ ($* == *-comprehensive.jar*) ]]; then #comprehensive包 if [[ ($di1lie=='root root root' )&&( $di2lie != '' )]] ; then #comprehensive起了,先杀再起 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms1500M -Xmx1500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$arg is start ready!" fi if [[ ( $di1lie == 'root root' )&&( $di2lie == '' ) ]]; then #comprehensive没起,就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms1500M -Xmx1500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$* is start readay!" fi elif [[ ($* == *-unify.jar*) ]]; then #unify包 if [[ ($di1lie=='root root root' )&&( $di2lie != '' )]] ; then #unify起了,先杀再起 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$arg is start ready!" fi if [[ ( $di1lie == 'root root' )&&( $di2lie == '' ) ]]; then #unify没起,就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$* is start readay!" fi elif [[ ($* == *-auc.jar*) ]]; then #auc包 if [[ ($di1lie=='root root root' )&&( $di2lie != '' )]] ; then #auc起了,先杀再起 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$arg is start ready!" fi if [[ ( $di1lie == 'root root' )&&( $di2lie == '' ) ]]; then #auc没起,就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms500M -Xmx500M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$* is start readay!" fi else #其他包 if [[ ($di1lie=='root root root' )&&( $di2lie != '' ) ]]; then #起了先杀再起111 kill -9 $di2lie nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$* is restart readay!" fi if [[ ( $di1lie == 'root root' )&&( $di2lie == '' ) ]]; then #没起就起 nohup $java_path/bin/java -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar "$abc/$*" > "$abc/$*.log" 2>&1 & echo "$* is start readay!" fi fi ;; #命令4 "findall") echo "$(pwd)/下有如下包:" for i in ${!FILE_NAME[*]}; do echo "${FILE_NAME[i]}" done printf "\n" echo "$(pwd)/下未启动的包有:" for i in ${!FILE_NAME[*]}; do no_id=$(ps -ef | grep ${FILE_NAME[i]} | grep -v "grep" | grep -v start123 | awk '{print $2}' | xargs) if [[ -z "${no_id}" ]]; then echo "${FILE_NAME[i]}!" fi done printf "\n" echo "$(pwd)/下启动的包有:" for i in ${!FILE_NAME[*]}; do no_id=$(ps -ef | grep ${FILE_NAME[i]} | grep -v "grep" | grep -v start123 | awk '{print $2}' | xargs) if [[ ! -z "${no_id}" ]]; then echo "${FILE_NAME[i]}已启动,进程ID为${no_id}" fi done esac done printf "\n" echo "结束jieshu" 如何让这个脚本,让通过ssh执行的这个脚本时,脚本能正确获取java环境
最新发布
07-31
<think>我们注意到脚本中使用了`readlink -f $(which javac)`来获取Java路径,这通常可以找到Java安装路径。但是,在通过SSH执行时,环境变量可能与交互式Shell不同,特别是当`.bashrc`或`/etc/profile`中设置了环境变量时。 问题分析: 1. 在SSH执行时,默认是非交互式、非登录Shell,因此不会加载`~/.bashrc`(除非SSH配置为启动登录Shell)或`/etc/profile`(对于登录Shell)。 2. 脚本开头尝试加载`/etc/profile`,这可以确保系统级的环境变量被加载。但是,用户级别的环境变量(如`~/.bashrc`中的设置)可能不会被加载。 解决方案: 为了确保Java环境变量正确设置,我们可以采取以下措施: 1. 在脚本中显式设置`JAVA_HOME`(如果知道路径),或者使用绝对路径调用Java。 2. 或者,在脚本中尝试从常见的环境文件加载环境变量(如`/etc/profile`和用户目录下的`.bashrc`),但要注意非交互式Shell不会自动加载这些文件。 但是,由于脚本已经尝试加载了`/etc/profile`,这应该可以获取系统级的Java设置(如果`/etc/profile`中设置了`JAVA_HOME`)。然而,如果Java是通过用户级别的配置(如`~/.bashrc`)设置的,那么可能不会生效。 改进建议: 我们可以尝试在脚本中加载用户目录下的`.bashrc`(如果存在),但要注意`.bashrc`可能包含一些仅用于交互式Shell的设置,这可能会导致问题。因此,我们可以有选择地加载环境变量。 另一种方法是:在SSH命令中指定环境变量,或者让SSH启动一个登录Shell(这样会加载用户的环境设置)。例如: ssh user@host "source ~/.bashrc; /path/to/script.sh" 但是,如果希望脚本自身能够适应,我们可以尝试在脚本中判断并加载用户的环境文件。 然而,在脚本中,我们更倾向于使用绝对路径来避免依赖环境变量。例如,如果我们知道Java安装路径,可以直接使用绝对路径。 但是,脚本中已经使用以下方式获取Java路径: java_path=$(dirname $(dirname $(readlink -f $(which javac)))) 这个命令在大多数情况下是有效的,因为它通过`which javac`找到`javac`的路径,然后解析其真实路径,再向上两级得到Java安装目录。 问题在于:在非交互式Shell中,`which`命令可能无法找到`javac`,因为PATH环境变量可能没有设置。 因此,我们需要确保PATH被正确设置。由于脚本开头已经加载了`/etc/profile`,这通常设置了系统级的PATH。如果还不够,我们可以尝试加载用户的环境文件。 修改脚本开头: # 加载系统配置文件 source /etc/profile # 加载当前用户的环境配置文件(如果存在) if [ -f ~/.bash_profile ]; then source ~/.bash_profile elif [ -f ~/.bash_login ]; then source ~/.bash_login elif [ -f ~/.profile ]; then source ~/.profile elif [ -f ~/.bashrc ]; then source ~/.bashrc fi 这样,在SSH执行时,脚本会尝试加载用户的环境设置,从而正确设置PATH。 但是,注意:如果这些文件中有输出(例如echo),可能会导致脚本输出不必要的日志。因此,我们需要确保这些环境文件在非交互式Shell中运行时不会产生输出。 另外,我们也可以考虑在脚本中直接设置PATH,例如: export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 然后再加上我们需要的路径(如Java的bin目录)。 然而,最可靠的方法还是使用绝对路径调用Java。但我们的脚本中已经通过`which javac`来定位Java,所以只要PATH正确,就能找到。 因此,修改脚本开头,增加加载用户环境文件的代码。 但是,注意:在SSH执行时,用户环境文件中的命令可能会失败(因为非交互式),或者产生输出。因此,我们可以尝试静默加载。 修改后的脚本开头部分: ```bash #!/bin/bash # 加载系统配置文件 source /etc/profile # 加载用户的环境配置文件(如果存在),并重定向错误和输出到/dev/null,避免输出干扰 [ -f ~/.bash_profile ] && source ~/.bash_profile >/dev/null 2>&1 [ -f ~/.bash_login ] && source ~/.bash_login >/dev/null 2>&1 [ -f ~/.profile ] && source ~/.profile >/dev/null 2>&1 [ -f ~/.bashrc ] && source ~/.bashrc >/dev/null 2>&1 # 其他代码... ``` 这样,脚本在SSH执行时应该能正确获取Java环境。 另外,我们注意到脚本中使用了`export java_path=$(dirname $(dirname $(readlink -f $(which javac))))`,这个命令在找不到`javac`时会出错。我们可以添加错误检查: ```bash which javac >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "Error: javac not found. Please ensure Java Development Kit (JDK) is installed and in the PATH." exit 1 fi ``` 但是,为了简化,我们也可以直接使用`java`命令(因为运行jar只需要java,不需要javac)。所以,我们可以改为查找`java`命令的路径: ```bash # 查找java命令的路径 java_bin=$(which java) if [ -z "$java_bin" ]; then echo "Error: java not found. Please ensure Java Runtime Environment (JRE) is installed and in the PATH." exit 1 fi java_path=$(dirname $(dirname $(readlink -f "$java_bin"))) ``` 但是注意,`which java`可能返回多个结果,但通常返回第一个。另外,`readlink -f`可以解析链接。 然而,在脚本中,我们实际使用`$java_path/bin/java`来启动Java。所以,我们可以直接使用找到的`java_bin`(即`$java_bin`)来启动,而不需要再构造路径。 因此,我们可以修改脚本,将`java_bin`作为Java可执行文件的路径: 原代码: nohup $java_path/bin/java ... 改为: nohup $java_bin ... 这样更直接。 修改步骤: 1. 将获取Java路径的部分改为获取`java`的绝对路径。 2. 替换脚本中所有`$java_path/bin/java`为`$java_bin`。 但是,注意:在脚本中,我们使用了`$java_path`来构造`bin/java`,而实际上我们通过`which java`已经得到了`java`的完整路径,所以可以直接使用。 修改后的代码: ```bash # 获取java的绝对路径 java_bin=$(which java) if [ -z "$java_bin" ]; then echo "Error: java not found. Please ensure Java Runtime Environment (JRE) is installed and in the PATH." exit 1 fi # 然后,在启动jar包的地方,使用$java_bin代替$java_path/bin/java ``` 例如: nohup $java_bin -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar ... 这样,即使Java的安装路径很特殊,也能正确使用。 但是,注意:在脚本中,我们使用了`export java_path`,但后续并没有使用这个变量(除了用来构造`$java_path/bin/java`)。如果我们改为使用`java_bin`,那么`java_path`就可以不用了。 因此,我们重构脚本: 1. 删除`export java_path`的定义,改为`java_bin`。 2. 在需要启动Java的地方,使用`$java_bin`。 另外,我们还需要处理另一个问题:在SSH执行时,`which java`可能还是找不到,因为PATH可能没有设置。所以,我们前面加载环境文件的步骤就很重要。 综合以上,我们修改脚本的开头部分,并替换所有启动Java命令的地方。 由于原脚本较长,我在这里只修改关键部分,并给出修改后的完整脚本开头。 修改后的脚本开头: ```bash #!/bin/bash # 加载系统配置文件 source /etc/profile # 加载用户的环境配置文件(如果存在) [ -f ~/.bash_profile ] && source ~/.bash_profile >/dev/null 2>&1 [ -f ~/.bash_login ] && source ~/.bash_login >/dev/null 2>&1 [ -f ~/.profile ] && source ~/.profile >/dev/null 2>&1 [ -f ~/.bashrc ] && source ~/.bashrc >/dev/null 2>&1 # 获取java的绝对路径 java_bin=$(which java) if [ -z "$java_bin" ]; then echo "Error: java not found. Please ensure Java Runtime Environment (JRE) is installed and in the PATH." exit 1 fi # 其他环境变量设置... export JVM_XM="-Xms256 -Xmx256" export JAR_NAMES export JAR_PID # ... 其余不变 ``` 然后,在启动jar包的地方,将`$java_path/bin/java`替换为`$java_bin`。 例如: nohup $java_bin -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar ... 注意:原脚本中使用了`$java_path`的地方都要检查,但只有启动Java命令的地方使用了。 由于原脚本很长,这里只给出修改示例,具体修改需要在整个脚本中搜索`$java_path/bin/java`并替换。 另外,原脚本中有一段: export java_id=$(ps -ef|grep java |grep -v grep |awk '{print $2}') 这个变量名与我们的`java_bin`冲突,我们不需要修改,因为它们是不同的变量。 但是,为了避免混淆,我们可以将`java_bin`变量名改为`JAVA_BIN`(大写),以区别于其他变量。 修改后的完整脚本较长,这里不全部展示,但关键修改已经说明。 最后,我们还需要注意:在通过SSH执行时,脚本中的`source`命令可能因为权限问题而失败(例如,用户目录下的配置文件不可读),因此需要确保这些文件可读。 总结修改: 1. 在开头加载环境配置文件,确保PATH设置正确。 2. 使用`which java`获取Java路径,并检查是否存在。 3. 将启动Java的命令改为使用`$JAVA_BIN`(或`$java_bin`)变量。 这样修改后,脚本在SSH执行时应该能正确找到Java环境。 注意:由于脚本较长,修改时请仔细检查替换。 由于无法直接运行测试,请根据实际情况调整。 如果问题仍然存在,可以在脚本中临时输出环境变量和PATH,用于调试: echo "PATH: $PATH" echo "JAVA_BIN: $JAVA_BIN" 这样可以帮助定位问题。 修改后的部分代码示例(仅开头和启动部分): ```bash #!/bin/bash #source ~/.bashrc source /etc/profile # 加载用户环境文件 [ -f ~/.bash_profile ] && source ~/.bash_profile >/dev/null 2>&1 [ -f ~/.bash_login ] && source ~/.bash_login >/dev/null 2>&1 [ -f ~/.profile ] && source ~/.profile >/dev/null 2>&1 [ -f ~/.bashrc ] && source ~/.bashrc >/dev/null 2>&1 # 获取Java可执行文件路径 JAVA_BIN=$(which java) if [ -z "$JAVA_BIN" ]; then echo "Error: java not found. Please ensure Java Runtime Environment (JRE) is installed and in the PATH." exit 1 fi # 其他原有代码... ``` 在启动jar包的地方,例如: nohup $JAVA_BIN -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar ... 替换所有类似的地方。 由于原脚本非常长,这里无法一一替换,但思路已经明确。 另外,原脚本中还有一处: java_path=$(dirname $(dirname $(readlink -f $(which javac)))) 我们不再需要,可以删除,因为我们使用`JAVA_BIN`。 但是,注意原脚本后面有使用`java_path`的地方,我们已经替换为`JAVA_BIN`,所以这个变量可以删除了。 所以,删除`export java_path=...`这一行。 最后,请根据实际情况测试调整。</think>要让脚本在通过SSH执行时正确获取Java环境,需要解决环境变量加载和路径识别问题。以下是关键修改方案: ### 1. 环境变量加载问题 SSH执行时默认加载的环境与交互式shell不同,需要显式加载环境文件: ```bash #!/bin/bash # 显式加载系统和个人环境文件 source /etc/profile [ -f ~/.bash_profile ] && source ~/.bash_profile [ -f ~/.bashrc ] && source ~/.bashrc ``` ### 2. Java路径识别优化 使用更可靠的Java路径获取方式: ```bash # 方法1:优先使用JAVA_HOME(如果已设置) if [ -n "$JAVA_HOME" ]; then java_bin="$JAVA_HOME/bin/java" # 方法2:使用which查找java路径 elif which java &>/dev/null; then java_bin=$(which java) # 方法3:尝试常见安装路径 else possible_paths=( "/usr/bin/java" "/usr/local/bin/java" "/opt/jdk*/bin/java" "/usr/lib/jvm/*/bin/java" ) for path in "${possible_paths[@]}"; do if [ -x "$path" ]; then java_bin="$path" break fi done fi # 验证Java是否找到 if [ -z "$java_bin" ]; then echo "ERROR: Java not found! Please install JDK." exit 1 fi ``` ### 3. 完整修改示例 以下是修改后的关键部分: ```bash #!/bin/bash # 显式加载环境配置 source /etc/profile [ -f ~/.bash_profile ] && source ~/.bash_profile [ -f ~/.bashrc ] && source ~/.bashrc # 可靠的Java路径获取 find_java() { # 1. 检查JAVA_HOME if [ -n "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ]; then echo "$JAVA_HOME/bin/java" return fi # 2. 检查PATH中的java type -p java &>/dev/null && echo java && return # 3. 扫描常见安装路径 local paths=( /usr/bin/java /usr/local/bin/java /opt/jdk*/bin/java /usr/lib/jvm/*/bin/java ) for path in "${paths[@]}"; do if [ -x "$path" ]; then echo "$path" return fi done # 未找到 echo "JAVA_NOT_FOUND" } java_bin=$(find_java) if [ "$java_bin" = "JAVA_NOT_FOUND" ]; then echo "ERROR: Java not found! Tried:" echo "1. JAVA_HOME: $JAVA_HOME" echo "2. System PATH" echo "3. Common install locations" exit 1 fi # 后续脚本中使用$java_bin代替原$java_path/bin/java # 示例修改启动命令: nohup "$java_bin" -Dfile.encoding=utf-8 -Xms256M -Xmx256M -jar "$jar_file" > "$log_file" 2>&1 & ``` ### 4. 其他优化建议 1. **移除不必要的导出**: ```bash # 移除这些全局导出 unset JAR_NAMES JAR_PID di1lie di2lie ``` 2. **路径引号处理**: ```bash # 所有路径变量使用双引号包裹 nohup "$java_bin" -jar "${FILE_NAME[i]}" > "${FILE_NAME[i]}.log" 2>&1 & ``` 3. **SSH执行测试命令**: ```bash ssh user@host 'source /etc/profile; source ~/.bashrc; /path/to/script.sh startall' ``` ### 修改后脚本优势 1. **三层Java查找机制**:优先使用JAVA_HOME,其次PATH查找,最后扫描常见路径 2. **环境隔离处理**:显式加载所有可能的环境配置文件 3. **错误处理**:明确的Java检测失败提示 4. **路径安全**:所有路径使用引号包裹,防止空格导致的错误 这些修改确保脚本在SSH、cron等非交互式环境中能可靠获取Java环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值