ProcessBuilder 运行 可以 bash 函数吗?
Can ProcessBuilder run a bash function?
安装 sdkman 后,将以下两行添加到我的 ~/.bashrc
:
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
并重新加载环境,名为 sdk
的函数在环境中变得可用:
$ type sdk
sdk is a function
sdk ()
{
COMMAND="";
QUALIFIER="";
case "$COMMAND" in
l)
COMMAND="list"
;;
ls)
COMMAND="list"
;;
v)
COMMAND="version"
;;
u)
COMMAND="use"
;;
i)
COMMAND="install"
;;
rm)
COMMAND="uninstall"
;;
c)
COMMAND="current"
;;
ug)
COMMAND="upgrade"
;;
d)
COMMAND="default"
;;
b)
COMMAND="broadcast"
;;
h)
COMMAND="home"
;;
e)
COMMAND="env"
;;
esac;
if [[ "$COMMAND" == "home" ]]; then
__sdk_home "$QUALIFIER" "";
return $?;
fi;
if [[ "$COMMAND" == "completion" ]]; then
return 0;
fi;
if [[ "$COMMAND" != "update" ]]; then
___sdkman_check_candidates_cache "$SDKMAN_CANDIDATES_CACHE" || return 1;
fi;
___sdkman_check_version_cache;
SDKMAN_AVAILABLE="true";
if [ -z "$SDKMAN_OFFLINE_MODE" ]; then
SDKMAN_OFFLINE_MODE="false";
fi;
__sdkman_update_broadcast_and_service_availability;
if [ -f "${SDKMAN_DIR}/etc/config" ]; then
source "${SDKMAN_DIR}/etc/config";
fi;
if [[ -z "$COMMAND" ]]; then
__sdk_help;
return 1;
fi;
CMD_FOUND="";
CMD_TARGET="${SDKMAN_DIR}/src/sdkman-${COMMAND}.sh";
if [[ -f "$CMD_TARGET" ]]; then
CMD_FOUND="$CMD_TARGET";
fi;
CMD_TARGET="${SDKMAN_DIR}/ext/sdkman-${COMMAND}.sh";
if [[ -f "$CMD_TARGET" ]]; then
CMD_FOUND="$CMD_TARGET";
fi;
if [[ -z "$CMD_FOUND" ]]; then
echo "";
__sdkman_echo_red "Invalid command: $COMMAND";
echo "";
__sdk_help;
fi;
local sdkman_valid_candidate=$(echo ${SDKMAN_CANDIDATES[@]} | grep -w "$QUALIFIER");
if [[ -n "$QUALIFIER" && "$COMMAND" != "help" && "$COMMAND" != "offline" && "$COMMAND" != "flush" && "$COMMAND" != "selfupdate" && "$COMMAND" != "env" && "$COMMAND" != "completion" && "$COMMAND" != "edit" && -z "$sdkman_valid_candidate" ]]; then
echo "";
__sdkman_echo_red "Stop! $QUALIFIER is not a valid candidate.";
return 1;
fi;
if [[ "$COMMAND" == "offline" && -n "$QUALIFIER" && -z $(echo "enable disable" | grep -w "$QUALIFIER") ]]; then
echo "";
__sdkman_echo_red "Stop! $QUALIFIER is not a valid offline mode.";
fi;
local final_rc=0;
local native_command="${SDKMAN_DIR}/libexec/${COMMAND}";
local converted_command_name=$(echo "$COMMAND" | tr '-' '_');
if [ -f "$native_command" ]; then
if [ -z "$QUALIFIER" ]; then
"$native_command";
else
if [ -z "" ]; then
"$native_command" "$QUALIFIER";
else
if [ -z "" ]; then
"$native_command" "$QUALIFIER" "";
else
"$native_command" "$QUALIFIER" "" "";
fi;
fi;
fi;
final_rc=$?;
else
if [ -n "$CMD_FOUND" ]; then
__sdk_"$converted_command_name" "$QUALIFIER" "" "";
final_rc=$?;
fi;
fi;
if [[ "$COMMAND" != "selfupdate" && "$sdkman_selfupdate_enable" == true ]]; then
__sdkman_auto_update "$SDKMAN_REMOTE_VERSION" "$SDKMAN_VERSION";
fi;
return $final_rc
}
您可以像 shell 中的普通命令一样使用它。例如:
$ sdk install java 17.0.2-tem
有没有办法使用 ProcessBuilder/Process
从 Java 内部 运行 sdk
?
除非我创建这样的脚本并从 Java:
调用它
#!/bin/bash
set -e
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 17.0.2-tem
我无法通过 ProcessBuilder 运行 sdk
命令:
final var processBuilder = ...;
processBuilder.command("sdk", "install", "java", "17.0.2-tem")
// or
processBuilder.command("/bin/bash", "-c", "sdk", "install", "java", "17.0.2-tem")
是否有任何其他替代方法允许从 Java 调用父环境中定义的函数?
Are there any other alternatives that would allow calling the functions defined in the parent environment from Java?
是的,但是您必须先 source
.bashrc
文件。
BufferedReader in = null;
OutputStreamWriter out = null;
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash").redirectErrorStream(true);
Process p = pb.start();
in = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
out = new OutputStreamWriter(p.getOutputStream(), StandardCharsets.UTF_8);
out.write("source ~/.bashrc\n");
out.write("sdkman\n");
out.write("exit\n");
out.flush();
String str;
while((str = in.readLine()) != null) {
System.out.println(str);
}
int response = p.waitFor();
System.out.println("response: " + response);
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
try { in.close(); } catch(Exception e) {}
try { out.close(); } catch(Exception e) {}
}
}
安装 sdkman 后,将以下两行添加到我的 ~/.bashrc
:
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
并重新加载环境,名为 sdk
的函数在环境中变得可用:
$ type sdk
sdk is a function
sdk ()
{
COMMAND="";
QUALIFIER="";
case "$COMMAND" in
l)
COMMAND="list"
;;
ls)
COMMAND="list"
;;
v)
COMMAND="version"
;;
u)
COMMAND="use"
;;
i)
COMMAND="install"
;;
rm)
COMMAND="uninstall"
;;
c)
COMMAND="current"
;;
ug)
COMMAND="upgrade"
;;
d)
COMMAND="default"
;;
b)
COMMAND="broadcast"
;;
h)
COMMAND="home"
;;
e)
COMMAND="env"
;;
esac;
if [[ "$COMMAND" == "home" ]]; then
__sdk_home "$QUALIFIER" "";
return $?;
fi;
if [[ "$COMMAND" == "completion" ]]; then
return 0;
fi;
if [[ "$COMMAND" != "update" ]]; then
___sdkman_check_candidates_cache "$SDKMAN_CANDIDATES_CACHE" || return 1;
fi;
___sdkman_check_version_cache;
SDKMAN_AVAILABLE="true";
if [ -z "$SDKMAN_OFFLINE_MODE" ]; then
SDKMAN_OFFLINE_MODE="false";
fi;
__sdkman_update_broadcast_and_service_availability;
if [ -f "${SDKMAN_DIR}/etc/config" ]; then
source "${SDKMAN_DIR}/etc/config";
fi;
if [[ -z "$COMMAND" ]]; then
__sdk_help;
return 1;
fi;
CMD_FOUND="";
CMD_TARGET="${SDKMAN_DIR}/src/sdkman-${COMMAND}.sh";
if [[ -f "$CMD_TARGET" ]]; then
CMD_FOUND="$CMD_TARGET";
fi;
CMD_TARGET="${SDKMAN_DIR}/ext/sdkman-${COMMAND}.sh";
if [[ -f "$CMD_TARGET" ]]; then
CMD_FOUND="$CMD_TARGET";
fi;
if [[ -z "$CMD_FOUND" ]]; then
echo "";
__sdkman_echo_red "Invalid command: $COMMAND";
echo "";
__sdk_help;
fi;
local sdkman_valid_candidate=$(echo ${SDKMAN_CANDIDATES[@]} | grep -w "$QUALIFIER");
if [[ -n "$QUALIFIER" && "$COMMAND" != "help" && "$COMMAND" != "offline" && "$COMMAND" != "flush" && "$COMMAND" != "selfupdate" && "$COMMAND" != "env" && "$COMMAND" != "completion" && "$COMMAND" != "edit" && -z "$sdkman_valid_candidate" ]]; then
echo "";
__sdkman_echo_red "Stop! $QUALIFIER is not a valid candidate.";
return 1;
fi;
if [[ "$COMMAND" == "offline" && -n "$QUALIFIER" && -z $(echo "enable disable" | grep -w "$QUALIFIER") ]]; then
echo "";
__sdkman_echo_red "Stop! $QUALIFIER is not a valid offline mode.";
fi;
local final_rc=0;
local native_command="${SDKMAN_DIR}/libexec/${COMMAND}";
local converted_command_name=$(echo "$COMMAND" | tr '-' '_');
if [ -f "$native_command" ]; then
if [ -z "$QUALIFIER" ]; then
"$native_command";
else
if [ -z "" ]; then
"$native_command" "$QUALIFIER";
else
if [ -z "" ]; then
"$native_command" "$QUALIFIER" "";
else
"$native_command" "$QUALIFIER" "" "";
fi;
fi;
fi;
final_rc=$?;
else
if [ -n "$CMD_FOUND" ]; then
__sdk_"$converted_command_name" "$QUALIFIER" "" "";
final_rc=$?;
fi;
fi;
if [[ "$COMMAND" != "selfupdate" && "$sdkman_selfupdate_enable" == true ]]; then
__sdkman_auto_update "$SDKMAN_REMOTE_VERSION" "$SDKMAN_VERSION";
fi;
return $final_rc
}
您可以像 shell 中的普通命令一样使用它。例如:
$ sdk install java 17.0.2-tem
有没有办法使用 ProcessBuilder/Process
从 Java 内部 运行 sdk
?
除非我创建这样的脚本并从 Java:
调用它#!/bin/bash
set -e
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 17.0.2-tem
我无法通过 ProcessBuilder 运行 sdk
命令:
final var processBuilder = ...;
processBuilder.command("sdk", "install", "java", "17.0.2-tem")
// or
processBuilder.command("/bin/bash", "-c", "sdk", "install", "java", "17.0.2-tem")
是否有任何其他替代方法允许从 Java 调用父环境中定义的函数?
Are there any other alternatives that would allow calling the functions defined in the parent environment from Java?
是的,但是您必须先 source
.bashrc
文件。
BufferedReader in = null;
OutputStreamWriter out = null;
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash").redirectErrorStream(true);
Process p = pb.start();
in = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
out = new OutputStreamWriter(p.getOutputStream(), StandardCharsets.UTF_8);
out.write("source ~/.bashrc\n");
out.write("sdkman\n");
out.write("exit\n");
out.flush();
String str;
while((str = in.readLine()) != null) {
System.out.println(str);
}
int response = p.waitFor();
System.out.println("response: " + response);
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
try { in.close(); } catch(Exception e) {}
try { out.close(); } catch(Exception e) {}
}
}