HADOOP-12441. Fixed shell-kill command behaviour to work correctly on some Linux distributions after HADOOP-12317. Contributed by Wangda Tan.

This commit is contained in:
Vinod Kumar Vavilapalli 2015-10-05 10:56:55 -07:00
parent b925cf1006
commit f1c19b9365
4 changed files with 57 additions and 17 deletions

View File

@ -1185,6 +1185,9 @@ Release 2.8.0 - UNRELEASED
HADOOP-12442. Display help if the command option to 'hdfs dfs' is not valid HADOOP-12442. Display help if the command option to 'hdfs dfs' is not valid
(nijel via vinayakumarb) (nijel via vinayakumarb)
HADOOP-12441. Fixed shell-kill command behaviour to work correctly on some
Linux distributions after HADOOP-12317. (Wangda Tan via vinodkv)
Release 2.7.2 - UNRELEASED Release 2.7.2 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -210,20 +210,26 @@ public static String[] getReadlinkCommand(String link) {
/** Return a command for determining if process with specified pid is alive. */ /** Return a command for determining if process with specified pid is alive. */
public static String[] getCheckProcessIsAliveCommand(String pid) { public static String[] getCheckProcessIsAliveCommand(String pid) {
return Shell.WINDOWS ? return getSignalKillCommand(0, pid);
new String[] { Shell.WINUTILS, "task", "isAlive", pid } :
isSetsidAvailable ?
new String[] { "kill", "-0", "--", "-" + pid } :
new String[] { "kill", "-0", pid };
} }
/** Return a command to send a signal to a given pid */ /** Return a command to send a signal to a given pid */
public static String[] getSignalKillCommand(int code, String pid) { public static String[] getSignalKillCommand(int code, String pid) {
return Shell.WINDOWS ? // Code == 0 means check alive
new String[] { Shell.WINUTILS, "task", "kill", pid } : if (Shell.WINDOWS) {
isSetsidAvailable ? if (0 == code) {
new String[] { "kill", "-" + code, "--", "-" + pid } : return new String[] { Shell.WINUTILS, "task", "isAlive", pid };
new String[] { "kill", "-" + code, pid }; } else {
return new String[] { Shell.WINUTILS, "task", "kill", pid };
}
}
if (isSetsidAvailable) {
// Use the shell-builtin as it support "--" in all Hadoop supported OSes
return new String[] { "bash", "-c", "kill -" + code + " -- -" + pid };
} else {
return new String[] { "bash", "-c", "kill -" + code + " " + pid };
}
} }
public static final String ENV_NAME_REGEX = "[A-Za-z_][A-Za-z0-9_]*"; public static final String ENV_NAME_REGEX = "[A-Za-z_][A-Za-z0-9_]*";
@ -386,6 +392,26 @@ public static final String getWinUtilsPath() {
return winUtilsPath; return winUtilsPath;
} }
public static final boolean isBashSupported = checkIsBashSupported();
private static boolean checkIsBashSupported() {
if (Shell.WINDOWS) {
return false;
}
ShellCommandExecutor shexec;
boolean supported = true;
try {
String[] args = {"bash", "-c", "echo 1000"};
shexec = new ShellCommandExecutor(args);
shexec.execute();
} catch (IOException ioe) {
LOG.warn("Bash is not supported by the OS", ioe);
supported = false;
}
return supported;
}
public static final boolean isSetsidAvailable = isSetsidSupported(); public static final boolean isSetsidAvailable = isSetsidSupported();
private static boolean isSetsidSupported() { private static boolean isSetsidSupported() {
if (Shell.WINDOWS) { if (Shell.WINDOWS) {

View File

@ -163,9 +163,9 @@ public void testGetCheckProcessIsAliveCommand() throws Exception {
expectedCommand = expectedCommand =
new String[]{ Shell.WINUTILS, "task", "isAlive", anyPid }; new String[]{ Shell.WINUTILS, "task", "isAlive", anyPid };
} else if (Shell.isSetsidAvailable) { } else if (Shell.isSetsidAvailable) {
expectedCommand = new String[]{ "kill", "-0", "--", "-" + anyPid }; expectedCommand = new String[] { "bash", "-c", "kill -0 -- -" + anyPid };
} else { } else {
expectedCommand = new String[]{"kill", "-0", anyPid}; expectedCommand = new String[]{ "bash", "-c", "kill -0 " + anyPid };
} }
Assert.assertArrayEquals(expectedCommand, checkProcessAliveCommand); Assert.assertArrayEquals(expectedCommand, checkProcessAliveCommand);
} }
@ -177,15 +177,14 @@ public void testGetSignalKillCommand() throws Exception {
anyPid); anyPid);
String[] expectedCommand; String[] expectedCommand;
if (Shell.WINDOWS) { if (Shell.WINDOWS) {
expectedCommand = expectedCommand =
new String[]{ Shell.WINUTILS, "task", "kill", anyPid }; new String[]{ Shell.WINUTILS, "task", "isAlive", anyPid };
} else if (Shell.isSetsidAvailable) { } else if (Shell.isSetsidAvailable) {
expectedCommand = expectedCommand = new String[] { "bash", "-c", "kill -9 -- -" + anyPid };
new String[]{ "kill", "-" + anySignal, "--", "-" + anyPid };
} else { } else {
expectedCommand = expectedCommand = new String[]{ "bash", "-c", "kill -9 " + anyPid };
new String[]{ "kill", "-" + anySignal, anyPid };
} }
Assert.assertArrayEquals(expectedCommand, checkProcessAliveCommand); Assert.assertArrayEquals(expectedCommand, checkProcessAliveCommand);
} }

View File

@ -43,6 +43,7 @@
import org.apache.hadoop.util.JvmPauseMonitor; import org.apache.hadoop.util.JvmPauseMonitor;
import org.apache.hadoop.util.NodeHealthScriptRunner; import org.apache.hadoop.util.NodeHealthScriptRunner;
import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.Shell;
import org.apache.hadoop.util.ShutdownHookManager; import org.apache.hadoop.util.ShutdownHookManager;
import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.YarnUncaughtExceptionHandler; import org.apache.hadoop.yarn.YarnUncaughtExceptionHandler;
@ -595,6 +596,17 @@ public NodeHealthCheckerService getNodeHealthChecker() {
private void initAndStartNodeManager(Configuration conf, boolean hasToReboot) { private void initAndStartNodeManager(Configuration conf, boolean hasToReboot) {
try { try {
// Failed to start if we're a Unix based system but we don't have bash.
// Bash is necessary to launch containers under Unix-based systems.
if (!Shell.WINDOWS) {
if (!Shell.isBashSupported) {
String message =
"Failing NodeManager start since we're on a "
+ "Unix-based system but bash doesn't seem to be available.";
LOG.fatal(message);
throw new YarnRuntimeException(message);
}
}
// Remove the old hook if we are rebooting. // Remove the old hook if we are rebooting.
if (hasToReboot && null != nodeManagerShutdownHook) { if (hasToReboot && null != nodeManagerShutdownHook) {