001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008 Sun Microsystems, Inc. 025 * Portions Copyright 2010-2015 ForgeRock AS. 026 */ 027package org.opends.server.tools; 028 029import static org.opends.messages.ToolMessages.*; 030import static org.opends.server.config.ConfigConstants.*; 031import static org.opends.server.util.DynamicConstants.*; 032import static org.opends.server.util.ServerConstants.*; 033import static org.opends.server.util.StaticUtils.*; 034 035import static com.forgerock.opendj.cli.Utils.*; 036 037import java.io.File; 038import java.io.OutputStream; 039import java.io.PrintStream; 040import java.io.PrintWriter; 041 042import org.forgerock.i18n.LocalizableMessage; 043import org.opends.server.core.DirectoryServer; 044import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler; 045import org.opends.server.loggers.JDKLogging; 046import org.opends.server.types.FilePermission; 047import org.opends.server.types.NullOutputStream; 048import org.opends.server.util.EmbeddedUtils; 049import org.opends.server.util.SetupUtils; 050 051import com.forgerock.opendj.cli.ArgumentException; 052import com.forgerock.opendj.cli.ArgumentParser; 053import com.forgerock.opendj.cli.BooleanArgument; 054import com.forgerock.opendj.cli.CommonArguments; 055import com.forgerock.opendj.cli.StringArgument; 056import com.forgerock.opendj.util.OperatingSystem; 057 058/** 059 * This program provides a tool that may be used to generate an RC script that 060 * can be used to start, stop, and restart the Directory Server, as well as to 061 * display its current status. It is only intended for use on UNIX-based 062 * systems that support the use of RC scripts in a location like /etc/init.d. 063 */ 064public class CreateRCScript 065{ 066 /** 067 * Parse the command line arguments and create an RC script that can be used 068 * to control the server. 069 * 070 * @param args The command-line arguments provided to this program. 071 */ 072 public static void main(String[] args) 073 { 074 int exitCode = main(args, System.out, System.err); 075 if (exitCode != 0) 076 { 077 System.exit(exitCode); 078 } 079 } 080 081 082 083 /** 084 * Parse the command line arguments and create an RC script that can be used 085 * to control the server. 086 * 087 * @param args The command-line arguments provided to this program. 088 * @param outStream The output stream to which standard output should be 089 * directed, or {@code null} if standard output should be 090 * suppressed. 091 * @param errStream The output stream to which standard error should be 092 * directed, or {@code null} if standard error should be 093 * suppressed. 094 * 095 * @return Zero if all processing completed successfully, or nonzero if an 096 * error occurred. 097 */ 098 public static int main(String[] args, OutputStream outStream, 099 OutputStream errStream) 100 { 101 PrintStream err = NullOutputStream.wrapOrNullStream(errStream); 102 JDKLogging.disableLogging(); 103 104 if (! OperatingSystem.isUnixBased()) 105 { 106 printWrappedText(err, ERR_CREATERC_ONLY_RUNS_ON_UNIX.get()); 107 return 1; 108 } 109 110 LocalizableMessage description = INFO_CREATERC_TOOL_DESCRIPTION.get(); 111 ArgumentParser argParser = 112 new ArgumentParser(CreateRCScript.class.getName(), description, false); 113 argParser.setShortToolDescription(REF_SHORT_DESC_CREATE_RC_SCRIPT.get()); 114 argParser.setVersionHandler(new DirectoryServerVersionHandler()); 115 116 BooleanArgument showUsage; 117 StringArgument javaArgs; 118 StringArgument javaHome; 119 StringArgument outputFile; 120 StringArgument userName; 121 122 try 123 { 124 outputFile = new StringArgument("outputfile", 'f', "outputFile", true, 125 false, true, INFO_PATH_PLACEHOLDER.get(), 126 null, null, 127 INFO_CREATERC_OUTFILE_DESCRIPTION.get()); 128 argParser.addArgument(outputFile); 129 130 131 userName = new StringArgument("username", 'u', "userName", false, false, 132 true, INFO_USER_NAME_PLACEHOLDER.get(), 133 null, null, 134 INFO_CREATERC_USER_DESCRIPTION.get()); 135 argParser.addArgument(userName); 136 137 138 javaHome = new StringArgument("javahome", 'j', "javaHome", false, false, 139 true, INFO_PATH_PLACEHOLDER.get(), null, 140 null, 141 INFO_CREATERC_JAVA_HOME_DESCRIPTION.get()); 142 argParser.addArgument(javaHome); 143 144 145 javaArgs = new StringArgument("javaargs", 'J', "javaArgs", false, false, 146 true, INFO_ARGS_PLACEHOLDER.get(), null, 147 null, 148 INFO_CREATERC_JAVA_ARGS_DESCRIPTION.get()); 149 argParser.addArgument(javaArgs); 150 151 152 showUsage = CommonArguments.getShowUsage(); 153 argParser.addArgument(showUsage); 154 argParser.setUsageArgument(showUsage); 155 } 156 catch (ArgumentException ae) 157 { 158 printWrappedText(err, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 159 return 1; 160 } 161 162 try 163 { 164 argParser.parseArguments(args); 165 } 166 catch (ArgumentException ae) 167 { 168 argParser.displayMessageAndUsageReference(err, ERR_ERROR_PARSING_ARGS.get(ae.getMessage())); 169 return 1; 170 } 171 172 if (argParser.usageOrVersionDisplayed()) 173 { 174 return 0; 175 } 176 177 EmbeddedUtils.initializeForClientUse(); 178 File serverRoot = DirectoryServer.getEnvironmentConfig().getServerRoot(); 179 if (serverRoot == null) 180 { 181 printWrappedText( 182 err, ERR_CREATERC_UNABLE_TO_DETERMINE_SERVER_ROOT.get(PROPERTY_SERVER_ROOT, ENV_VAR_INSTALL_ROOT)); 183 return 1; 184 } 185 186 // Determine the path to the Java installation that should be used. 187 String javaHomeDir; 188 if (javaHome.isPresent()) 189 { 190 File f = new File(javaHome.getValue()); 191 if (!f.exists() || !f.isDirectory()) 192 { 193 printWrappedText(err, ERR_CREATERC_JAVA_HOME_DOESNT_EXIST.get(javaHome.getValue())); 194 return 1; 195 } 196 197 javaHomeDir = f.getAbsolutePath(); 198 } 199 else 200 { 201 javaHomeDir = System.getenv(SetupUtils.OPENDJ_JAVA_HOME); 202 } 203 204 boolean isFreeBSD = OperatingSystem.getOperatingSystem() == OperatingSystem.FREEBSD; 205 206 String suString = ""; 207 String EscQuote1 = "\""; 208 String EscQuote2 = ""; 209 210 if (userName.isPresent()) 211 { 212 String suCmd = "/bin/su"; 213 File f = new File(suCmd); 214 if (! f.exists()) 215 { 216 suCmd = "/usr/bin/su"; 217 File f2 = new File(suCmd); 218 if (! f2.exists()) 219 { 220 // Default to /bin/su anyway 221 suCmd = "/bin/su"; 222 } 223 } 224 String asMeFlag = isFreeBSD ? " -m " : " "; 225 suString = suCmd + asMeFlag + userName.getValue() + " -c "; 226 EscQuote1 = ""; 227 EscQuote2 = "\""; 228 } 229 230 231 // Start writing the output file. 232 try 233 { 234 File f = new File(outputFile.getValue()); 235 PrintWriter w = new PrintWriter(f); 236 237 w.println("#!/bin/sh"); 238 w.println("#"); 239 240 for (String headerLine : CDDL_HEADER_LINES) 241 { 242 w.println("# " + headerLine); 243 } 244 245 if (isFreeBSD) { 246 w.println("# PROVIDE: opendj"); 247 w.println("# REQUIRE: LOGIN"); 248 w.println("# KEYWORD: shutdown"); 249 w.println(); 250 w.println(". /etc/rc.subr"); 251 w.println("name=\"opendj\""); 252 w.println("rcvar=opendj_enable"); 253 w.println(); 254 w.println("start_cmd=\"${name}_start\""); 255 w.println("stop_cmd=\"${name}_stop\""); 256 w.println("restart_cmd=\"${name}_restart\""); 257 w.println("status_cmd=\"${name}_status\""); 258 w.println(); 259 w.println("load_rc_config ${name}"); 260 w.println(": ${opendj_enable:=no}"); 261 w.println(": ${opendj_msg=\"OpenDJ not started.\"}"); 262 } else { 263 w.println("# chkconfig: 345 95 5"); 264 w.println("# description: Control the " + SHORT_NAME + " Directory Server"); 265 } 266 w.println(); 267 268 w.println("# Set the path to the " + SHORT_NAME + " instance to manage"); 269 w.println("INSTALL_ROOT=\"" + serverRoot.getAbsolutePath() + "\""); 270 w.println("export INSTALL_ROOT"); 271 w.println(); 272 w.println("cd ${INSTALL_ROOT}"); 273 w.println(); 274 275 if (javaHomeDir != null) 276 { 277 w.println("# Specify the path to the Java installation to use"); 278 w.println("OPENDJ_JAVA_HOME=\"" + javaHomeDir + "\""); 279 w.println("export OPENDJ_JAVA_HOME"); 280 w.println(); 281 } 282 283 if (javaArgs.isPresent()) 284 { 285 w.println("# Specify arguments that should be provided to the JVM"); 286 w.println("OPENDJ_JAVA_ARGS=\"" + javaArgs.getValue() + "\""); 287 w.println("export OPENDJ_JAVA_ARGS"); 288 w.println(); 289 } 290 291 if (isFreeBSD) { 292 w.println("if [ \"x${opendj_java_home}\" != \"x\" ]; then"); 293 w.println(" OPENDJ_JAVA_HOME=\"${opendj_java_home}\""); 294 w.println(" export OPENDJ_JAVA_HOME"); 295 w.println("fi"); 296 w.println("if [ \"x${opendj_java_args}\" != \"x\" ]; then"); 297 w.println(" OPENDJ_JAVA_ARGS=\"${opendj_java_args}\""); 298 w.println(" export OPENDJ_JAVA_ARGS"); 299 w.println("fi"); 300 w.println("if [ \"x${opendj_install_root}\" != \"x\" ]; then"); 301 w.println(" INSTALL_ROOT=\"${opendj_install_root}\""); 302 w.println(" export INSTALL_ROOT"); 303 w.println("fi"); 304 w.println(); 305 w.println("opendj_chdir=\"${INSTALL_ROOT}\""); 306 w.println("extra_commands=\"status\""); 307 w.println(); 308 w.println("opendj_start()"); 309 w.println("{"); 310 w.println(" if [ -n \"$rc_quiet\" ]; then"); 311 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/start-ds" + EscQuote2); 312 w.println(" else"); 313 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/start-ds" + EscQuote1 + " --quiet" + EscQuote2); 314 w.println(" fi"); 315 w.println("}"); 316 w.println("opendj_stop()"); 317 w.println("{"); 318 w.println(" if [ -n \"$rc_quiet\" ]; then"); 319 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote2); 320 w.println(" else"); 321 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote1 + " --quiet" + EscQuote2); 322 w.println(" fi"); 323 w.println("}"); 324 w.println("opendj_restart()"); 325 w.println("{"); 326 w.println(" if [ -n \"$rc_quiet\" ]; then"); 327 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote1 + " --restart" + EscQuote2); 328 w.println(" else"); 329 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote1 + " --restart --quiet" + EscQuote2); 330 w.println(" fi"); 331 w.println("}"); 332 w.println("opendj_status()"); 333 w.println("{"); 334 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/status" + EscQuote2); 335 w.println("}"); 336 w.println(); 337 w.println("pidfile=\"${INSTALL_ROOT}/logs/server.pid\""); 338 w.println(); 339 w.println("run_rc_command \"$1\""); 340 } else { 341 w.println("# Determine what action should be performed on the server"); 342 w.println("case \"${1}\" in"); 343 w.println("start)"); 344 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/start-ds" + EscQuote1 + " --quiet" + EscQuote2); 345 w.println(" exit ${?}"); 346 w.println(" ;;"); 347 w.println("stop)"); 348 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote1 + " --quiet" + EscQuote2); 349 w.println(" exit ${?}"); 350 w.println(" ;;"); 351 w.println("restart)"); 352 w.println(" " + suString + "\"${INSTALL_ROOT}/bin/stop-ds" + EscQuote1 + " --restart --quiet" + EscQuote2); 353 w.println(" exit ${?}"); 354 w.println(" ;;"); 355 w.println("*)"); 356 w.println(" echo \"Usage: $0 { start | stop | restart }\""); 357 w.println(" exit 1"); 358 w.println(" ;;"); 359 w.println("esac"); 360 w.println(); 361 } 362 w.close(); 363 364 FilePermission.setPermissions(f, FilePermission.decodeUNIXMode("755")); 365 } 366 catch (Exception e) 367 { 368 printWrappedText(err, ERR_CREATERC_CANNOT_WRITE.get(getExceptionMessage(e))); 369 return 1; 370 } 371 372 // If we've gotten here, then everything has completed successfully. 373 return 0; 374 } 375} 376