Linux Shell之init脚本与activemq init脚本设计亮点分析

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/1680420

上一篇博文《Linux下Apache ActiveMQ5.9的安装配置与测试》中详细叙述了activemq的安装配置和如何利用java小程序测试activemq是否正常工作。此篇文章将继续剖解activemq中的一些精华内容,从activemq的init脚本说起。init(initialization)脚本又叫服务控制脚本,可以利用此脚本启动、停止、重新启动、重新载入配置、查看运行状态等等,通常init脚本的写法遵循System V init script的写法,能够用service命令对服务或者进程进行启动、停止、重新启动、重新载入配置、查看运行状态等操作。

init脚本通常具有如下特性:

1.使用系统自带的预定义的init函数,这一套函数通常在一个文件中,根据不同的Linux发行版本文件的位置和内容也不一样,例如Ubuntu下是/lib/lsb/init-functions以及/lib/lsb/init-functions.d/下的一些子文件,CentOS下是/etc/init.d/functions。

2.参数灵活配置,既可以在init脚本中设定可变的脚本参数,也可以引入其他文件中的配置参数

3.严谨的判断逻辑,几乎能捕获并处理所有的异常,例如函数与命令的返回值检测、文件和执行文件以及参数是否存在的判断,甚至是否是softlink文件也考虑在内

4.良好的可管理性和可移植性性,可管理性体现在针对某一服务或进程多种操作,可移植性体现在将此脚本移植到其他相似系统上照样可以执行或者只需要少量的改动就能运行,例如一个更方便的例子,手动编译安装的nginx、httpd等可以直接利用yum或者apt-get安装得到的init脚本,改动一下安装路径做一下文件链接就可以用了,省却自己编写init脚本的麻烦

下面是activemq的一个init脚本的例子,该脚本有四大亮点:

亮点1:没用使用系统提供的init公共函数;

亮点2:正确处理softlink invoke可能导致的异常;

亮点3:自动导入(生成)配置文件,而且是从自身导入

亮点4:支持多实例部署,通过不同的配置文件实现多实例运行


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

#!/bin/sh

# ------------------------------------------------------------------------

# Licensed to the Apache Software Foundation (ASF) under one or more

# contributor license agreements.  See the NOTICE file distributed with

# this work for additional information regarding copyright ownership.

# The ASF licenses this file to You under the Apache License, Version 2.0

# (the "License"); you may not use this file except in compliance with

# the License.  You may obtain a copy of the License at

#

# http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

# ------------------------------------------------------------------------

#

# This script controls standalone Apache ActiveMQ service processes.

# To ensure compatibility to macosx and cygwin we do not utilize

# lsb standard infrastructure for controlling daemons like

# "start-stop-daemon".

#

# See also http://activemq.apache.org/activemq-command-line-tools-reference.html

# for additional commandline arguments

#

# Authors:

# Marc Schoechlin <ms@256bit.org>

 

# ------------------------------------------------------------------------

# CONFIGURATION

ACTIVEMQ_CONFIGS="/etc/default/activemq $HOME/.activemqrc"

 

# Backup invocation parameters

COMMANDLINE_ARGS="$@"

 

# For using instances

if basename $0 | grep "activemq-instance-" /dev/null);then

   INST="`basename $0|sed 's/^activemq-instance-//;s/\.sh$//'`"

   ACTIVEMQ_CONFIGS="/etc/default/activemq-instance-${INST} $HOME/.activemqrc-instance-${INST}"

   echo "INFO: Using alternative activemq configuration files: $ACTIVEMQ_CONFIGS"

fi

 

## START:DEFAULTCONFIG

# ------------------------------------------------------------------------

# Configuration file for running Apache Active MQ as standalone provider

#

# This file overwrites the predefined settings of the sysv init-script

#

# Active MQ installation dir

if [ -z "$ACTIVEMQ_HOME" ] ; then

  # try to find ACTIVEMQ

  if [ -d /opt/activemq ] ; then

    ACTIVEMQ_HOME=/opt/activemq

  fi

 

  if [ -d "${HOME}/opt/activemq" ] ; then

    ACTIVEMQ_HOME="${HOME}/opt/activemq"

  fi

 

  ## resolve links - $0 may be a link to activemq's home

  PRG="$0"

  progname=`basename "$0"`

  saveddir=`pwd`

 

  # need this for relative symlinks

  dirname_prg=`dirname "$PRG"`

  cd "$dirname_prg"

 

  while [ -h "$PRG" ] ; do

    ls=`ls -ld "$PRG"`

    link=`expr "$ls" '.*-> \(.*\)$'`

    if expr "$link" '.*/.*' /dev/nullthen

    PRG="$link"

    else

    PRG=`dirname "$PRG"`"/$link"

    fi

  done

 

  ACTIVEMQ_HOME=`dirname "$PRG"`/..

 

  cd "$saveddir"

 

  # make it fully qualified

  ACTIVEMQ_HOME=`cd "$ACTIVEMQ_HOME" && pwd`

fi

 

if [ -z "$ACTIVEMQ_BASE" ] ; then

  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"

fi

 

# Active MQ configuration directory

if [ -z "$ACTIVEMQ_CONF" ] ; then

 

    # For backwards compat with old variables we let ACTIVEMQ_CONFIG_DIR set ACTIVEMQ_CONF

    if [ -z "$ACTIVEMQ_CONFIG_DIR" ] ; then

        ACTIVEMQ_CONF="$ACTIVEMQ_BASE/conf"

    else

        ACTIVEMQ_CONF="$ACTIVEMQ_CONFIG_DIR"

    fi

fi

 

# Configure a user with non root priviledges, if no user is specified do not change user

if [ -z "$ACTIVEMQ_USER" ] ; then

    ACTIVEMQ_USER=""

fi

 

# Active MQ data directory

if [ -z "$ACTIVEMQ_DATA" ] ; then

 

    # For backwards compat with old variables we let ACTIVEMQ_DATA_DIR set ACTIVEMQ_DATA

    if [ -z "$ACTIVEMQ_DATA_DIR" ] ; then

        ACTIVEMQ_DATA="$ACTIVEMQ_BASE/data"

    else

        ACTIVEMQ_DATA="$ACTIVEMQ_DATA_DIR"

    fi

fi

 

if [ -z "$ACTIVEMQ_TMP" ] ; then

  ACTIVEMQ_TMP="$ACTIVEMQ_BASE/tmp"

fi

 

setCurrentUser(){

   CUSER=`whoami 2>/dev/null`

 

   # Solaris fix

   if [ ! $? -eq 0 ]; then

      CUSER=`/usr/ucb/whoami 2>/dev/null`

   fi

}

 

if [ ! -d "$ACTIVEMQ_DATA" ]; then

   setCurrentUser

   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" "$CUSER" ] );then

        mkdir $ACTIVEMQ_DATA

   elif "`id -u`" "0" ];then

      su -c "mkdir $ACTIVEMQ_DATA" - $ACTIVEMQ_USER;

   fi

fi

 

# Location of the pidfile

if [ -z "$ACTIVEMQ_PIDFILE" ]; then

  ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq-`hostname`.pid"

fi

 

# Location of the java installation

# Specify the location of your java installation using JAVA_HOME, or specify the

# path to the "java" binary using JAVACMD

# (set JAVACMD to "auto" for automatic detection)

#JAVA_HOME=""

JAVACMD="auto"

 

# Set jvm memory configuration

if [ -z "$ACTIVEMQ_OPTS_MEMORY" ] ; then

    ACTIVEMQ_OPTS_MEMORY="-Xms1G -Xmx1G"

fi

 

# Uncomment to enable audit logging

#ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -Dorg.apache.activemq.audit=true"

 

# Set jvm jmx configuration

# This enables jmx access over a configured jmx-tcp-port.

# You have to configure the first four settings if you run a ibm jvm, caused by the

# fact that IBM's jvm does not support VirtualMachine.attach(PID).

# JMX access is needed for quering a running activemq instance to gain data or to

# trigger management operations.

#

# Example for ${ACTIVEMQ_CONF}/jmx.access:

# ---

# # The "monitorRole" role has readonly access.

# # The "controlRole" role has readwrite access.

# monitorRole readonly

# controlRole readwrite

# ---

#

# Example for ${ACTIVEMQ_CONF}/jmx.password:

# ---

# # The "monitorRole" role has password "abc123".

# # # The "controlRole" role has password "abcd1234".

# monitorRole abc123

# controlRole abcd1234

# ---

#

# ACTIVEMQ_SUNJMX_START="-Dcom.sun.management.jmxremote.port=11099 "

# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.password.file=${ACTIVEMQ_CONF}/jmx.password"

# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.access.file=${ACTIVEMQ_CONF}/jmx.access"

# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.ssl=false"

ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote"

 

# Set jvm jmx configuration for controlling the broker process

# You only have to configure the first four settings if you run a ibm jvm, caused by the

# fact that IBM's jvm does not support VirtualMachine.attach(PID)

# (see also com.sun.management.jmxremote.port, .jmx.password.file and .jmx.access.file )

#ACTIVEMQ_SUNJMX_CONTROL="--jmxurl service:jmx:rmi:///jndi/rmi://127.0.0.1:1099/jmxrmi --jmxuser controlRole --jmxpassword abcd1234"

ACTIVEMQ_SUNJMX_CONTROL=""

 

# Specify the queue manager URL for using "browse" option of sysv initscript

if [ -z "$ACTIVEMQ_QUEUEMANAGERURL" ]; then

    ACTIVEMQ_QUEUEMANAGERURL="--amqurl tcp://localhost:61616"

fi

 

# Set additional JSE arguments

ACTIVEMQ_SSL_OPTS="$SSL_OPTS"

 

# Uncomment to enable YourKit profiling

#ACTIVEMQ_DEBUG_OPTS="-agentlib:yjpagent"

 

# Uncomment to enable remote debugging

#ACTIVEMQ_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"

 

# ActiveMQ tries to shutdown the broker by jmx,

# after a specified number of seconds send SIGKILL

if [ -z "$ACTIVEMQ_KILL_MAXSECONDS" ]; then

    ACTIVEMQ_KILL_MAXSECONDS=30

fi

 

## END:DEFAULTCONFIG

 

# ------------------------------------------------------------------------

# LOAD CONFIGURATION

 

# load activemq configuration

CONFIG_LOAD="no"

for ACTIVEMQ_CONFIG in $ACTIVEMQ_CONFIGS;do

   if [ -f "$ACTIVEMQ_CONFIG" ] ; then

     ( . $ACTIVEMQ_CONFIG >/dev/null 2>&1 )

     if "$?" != "0" ];then

      echo "ERROR: There are syntax errors in '$ACTIVEMQ_CONFIG'"

      exit 1

     else

       echo "INFO: Loading '$ACTIVEMQ_CONFIG'"

       . $ACTIVEMQ_CONFIG

      CONFIG_LOAD="yes"

     fi

   fi

done

 

# inform user that default configuration is loaded, no suitable configfile found

if "$CONFIG_LOAD" != "yes" ];then

   if "$1" != "setup" ];then

      echo "INFO: Using default configuration";

      echo "(you can configure options in one of these file: $ACTIVEMQ_CONFIGS)"

      echo

      echo "INFO: Invoke the following command to create a configuration file"

      CONFIGS=`echo $ACTIVEMQ_CONFIGS|sed 's/[ ][ ]*/ | /'`

      echo "$0 setup [ $CONFIGS ]"

      echo

   fi

fi

 

if [ -z "$ACTIVEMQ_OPTS" ] ; then

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Djava.util.logging.config.file=logging.properties -Dhawtio.realm=activemq -Dhawtio.role=admins -Dhawtio.rolePrincipalClasses=org.apache.activemq.jaas.GroupPrincipal -Djava.security.auth.login.config=$ACTIVEMQ_CONF/login.config"

fi

 

# create configuration if requested

if "$1" "setup" ];then

   if [ -z "$2" ];then

      echo "ERROR: Specify configuration file"

      exit 1

   fi

   echo "INFO: Creating configuration file: $2"

   (

   P_STATE="0"

   while read LINE ;do

      if (echo "$LINE" grep "START:DEFAULTCONFIG" >/dev/null );then

         P_STATE="1"

         continue;

      fi

      if (echo "$LINE" grep "END:DEFAULTCONFIG" >/dev/null);then

         P_STATE="0"

         break;

      fi

      if "$P_STATE" -eq "1" ];then

         echo $LINE

      fi

   done < $0

   ) > $2

 

   setCurrentUser

 

   echo "INFO: It's recommend to limit access to '$2' to the priviledged user"

   echo "INFO: (recommended: chown '$CUSER':nogroup '$2'; chmod 600 '$2')"

   exit $?

fi

 

# ------------------------------------------------------------------------

# OS SPECIFIC SUPPORT

 

OSTYPE="unknown"

 

case "`uname`" in

  CYGWIN*) OSTYPE="cygwin" ;;

  Darwin*)

           OSTYPE="darwin"

           if [ -z "$JAVA_HOME" ] && [ "$JAVACMD" "auto" ];then

             JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home

           fi

           ;;

esac

 

# For Cygwin, ensure paths are in UNIX format before anything is touched

if "$OSTYPE" "cygwin" ]; then

  [ -n "$ACTIVEMQ_HOME" ] &&

    ACTIVEMQ_HOME="`cygpath --unix "$ACTIVEMQ_HOME"`"

  [ -n "$JAVA_HOME" ] &&

    JAVA_HOME="`cygpath --unix "$JAVA_HOME"`"

  [ -n "$CLASSPATH" ] &&

    CLASSPATH="`cygpath --path --unix "$CLASSPATH"`"

fi

 

# Detect the location of the java binary

if [ -z "$JAVACMD" ] || [ "$JAVACMD" "auto" ] ; then

  if [ -n "$JAVA_HOME"  ] ; then

    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then

      # IBM's JDK on AIX uses strange locations for the executables

      JAVACMD="$JAVA_HOME/jre/sh/java"

    else

      JAVACMD="$JAVA_HOME/bin/java"

    fi

  fi

fi

 

# Hm, we still do not know the location of the java binary

if [ ! -x "$JAVACMD" ] ; then

    JAVACMD=`which java 2> /dev/null `

    if [ -z "$JAVACMD" ] ; then

        JAVACMD=java

    fi

fi

# Stop here if no java installation is defined/found

if [ ! -x "$JAVACMD" ] ; then

  echo "ERROR: Configuration variable JAVA_HOME or JAVACMD is not defined correctly."

  echo "       (JAVA_HOME='$JAVAHOME', JAVACMD='$JAVACMD')"

  exit 1

fi

 

echo "INFO: Using java '$JAVACMD'"

 

if [ -z "$ACTIVEMQ_BASE" ] ; then

  ACTIVEMQ_BASE="$ACTIVEMQ_HOME"

fi

 

# For Cygwin, switch paths to Windows format before running java if [ "$OSTYPE" = "cygwin" ]; then

if "$OSTYPE" "cygwin" ];then

  ACTIVEMQ_HOME=`cygpath --windows "$ACTIVEMQ_HOME"`

  ACTIVEMQ_BASE=`cygpath --windows "$ACTIVEMQ_BASE"`

  ACTIVEMQ_CONF=`cygpath --windows "$ACTIVEMQ_CONF"`

  ACTIVEMQ_DATA=`cygpath --windows "$ACTIVEMQ_DATA"`

  ACTIVEMQ_CLASSPATH=`cygpath --path --windows "$ACTIVEMQ_CLASSPATH"`

  JAVA_HOME=`cygpath --windows "$JAVA_HOME"`

  CLASSPATH=`cygpath --path --windows "$CLASSPATH"`

  CYGHOME=`cygpath --windows "$HOME"`

  ACTIVEMQ_TMP=`cygpath --windows "$ACTIVEMQ_TMP"`

  if [ -n "$CYGHOME" ]; then

      ACTIVEMQ_CYGWIN="-Dcygwin.user.home=\"$CYGHOME\""

  fi

fi

 

# Set default classpath

# Add instance conf dir before AMQ install conf dir to pick up instance-specific classpath entries first

ACTIVEMQ_CLASSPATH="${ACTIVEMQ_CONF};${ACTIVEMQ_CLASSPATH}"

 

# Start the ActiveMQ JAR

#

#

# @ARG1 : the name of the PID-file

#         If specified, this function starts the java process in background as a daemon

#         and stores the pid of the created process in the file.

#         Output on stdout/stderr will be supressed if this parameter is specified

# @RET  : If unless 0 something went wrong

#

# Note: This function uses a lot of globally defined variables

# - if $ACTIVEMQ_USER is set, the function tries starts the java process whith the specified

#   user

invokeJar(){

   PIDFILE="$1"

   RET="1"

 

   if [ ! -f "${ACTIVEMQ_HOME}/bin/activemq.jar" ];then

    echo "ERROR: '${ACTIVEMQ_HOME}/bin/activemq.jar' does not exist"

    exit 1

   fi

 

   setCurrentUser

 

   if ( [ -z "$ACTIVEMQ_USER" ] || [ "$ACTIVEMQ_USER" "$CUSER" ] );then

      DOIT_PREFIX="sh -c "

      DOIT_POSTFIX=";"

   elif "`id -u`" "0" ];then

      DOIT_PREFIX="su -c "

      DOIT_POSTFIX=" - $ACTIVEMQ_USER"

      echo "INFO: changing to user '$ACTIVEMQ_USER' to invoke java"

   fi

   # Execute java binary

   if [ -n "$PIDFILE" ] && [ "$PIDFILE" != "stop" ];then

      $DOIT_PREFIX "$JAVACMD $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \

              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \

              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \

              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \

              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \

              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \

              $ACTIVEMQ_CYGWIN \

              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS >/dev/null 2>&1 &

              RET=\"\$?\"; APID=\"\$!\";

              echo \$APID > $PIDFILE;

              echo \"INFO: pidfile created : '$PIDFILE' (pid '\$APID')\";exit \$RET" $DOIT_POSTFIX

      RET="$?"

   elif [ -n "$PIDFILE" ] && [ "$PIDFILE" "stop" ];then

          PID=`cat $ACTIVEMQ_PIDFILE`

          $DOIT_PREFIX "$JAVACMD $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \

              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \

              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \

              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \

              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \

              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \

              $ACTIVEMQ_CYGWIN \

              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS --pid $PID &

              RET=\"\$?\"; APID=\"\$!\";

              echo \$APID > $ACTIVEMQ_DATA/stop.pid; exit \$RET" $DOIT_POSTFIX

      RET="$?"

   else

      $DOIT_PREFIX "$JAVACMD $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \

              -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \

              -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \

              -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \

              -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \

              -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \

              $ACTIVEMQ_CYGWIN \

              -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS" $DOIT_POSTFIX

      RET="$?"

   fi

   return $RET

}

 

# Check if ActiveMQ is running

#

# @RET  : 0 => the activemq process is running

#         1 => process id in $ACTIVEMQ_PIDFILE does not exist anymore

#         2 => something is wrong with the pid file

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_PIDFILE : the name of the pid file

 

 

checkRunning(){

    if [ -f "$ACTIVEMQ_PIDFILE" ]; then

       if  [ -z "`cat $ACTIVEMQ_PIDFILE`" ];then

        echo "ERROR: Pidfile '$ACTIVEMQ_PIDFILE' exists but contains no pid"

        return 2

       fi

       PID=`cat $ACTIVEMQ_PIDFILE`

       RET=`ps -p $PID|grep java`

       if [ -n "$RET" ];then

         return 0;

       else

         return 1;

       fi

    else

         return 1;

    fi

}

 

checkStopRunning(){

    PID=$ACTIVEMQ_DATA/stop.pid

    if [ -f "$PID" ]; then

       if  [ -z "`cat $PID`" ];then

        echo "ERROR: Pidfile '$PID' exists but contains no pid"

        return 2

       fi

       THEPID=`cat $PID`

       RET=`ps -p $THEPID|grep java`

       if [ -n "$RET" ];then

         return 0;

       else

         return 1;

       fi

    else

         return 1;

    fi

}

 

# Check if ActiveMQ is running

#

# @RET  : 0 => the activemq process is running

#         1 => the activemq process is not running

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_PIDFILE : the name of the pid file

 

 

invoke_status(){

    if ( checkRunning );then

         PID=`cat $ACTIVEMQ_PIDFILE`

         echo "ActiveMQ is running (pid '$PID')"

         exit 0

    fi

    echo "ActiveMQ not running"

    exit 1

}

 

# Start ActiveMQ if not already running

#

# @RET  : 0 => is now started, is already started

#         !0 => something went wrong

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_PIDFILE      : the name of the pid file

# - $ACTIVEMQ_OPTS         : Additional options

# - $ACTIVEMQ_SUNJMX_START : options for JMX settings

# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

 

invoke_start(){

    if ( checkRunning );then

      PID=`cat $ACTIVEMQ_PIDFILE`

      echo "INFO: Process with pid '$PID' is already running"

      exit 0

    fi

 

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

 

    echo "INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details"

    invokeJar $ACTIVEMQ_PIDFILE

    exit "$?"

}

 

# Start ActiveMQ in foreground (for debugging)

#

# @RET  : 0 => is now started, is already started

#         !0 => something went wrong

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_PIDFILE      : the name of the pid file

# - $ACTIVEMQ_OPTS         : Additional options

# - $ACTIVEMQ_SUNJMX_START : options for JMX settings

# - $ACTIVEMQ_SSL_OPTS     : options for SSL encryption

 

invoke_console(){

    if ( checkRunning );then

      echo "ERROR: ActiveMQ is already running"

      exit 1

    fi

 

    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\""

 

    COMMANDLINE_ARGS="start `echo $COMMANDLINE_ARGS|sed 's,^console,,'`"

    echo "INFO: Starting in foreground, this is just for debugging purposes (stop process by pressing CTRL+C)"

    invokeJar

    exit "$?"

}

 

# Stop ActiveMQ

#

# @RET  : 0 => stop was successful

#         !0 => something went wrong

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_PIDFILE         : the name of the pid file

# - $ACTIVEMQ_KILL_MAXSECONDS : the number of seconds to wait for termination of broker after sending

#                              shutdown signal by jmx interface

 

invoke_stop(){

    RET="1"

    if ( checkRunning );then

       ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

       COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"

       invokeJar "stop"

       RET="$?"

       PID=`cat $ACTIVEMQ_PIDFILE`

       echo "INFO: Waiting at least $ACTIVEMQ_KILL_MAXSECONDS seconds for regular process termination of pid '$PID' : "

       FOUND="0"

       i=1

       while [ $i != $ACTIVEMQ_KILL_MAXSECONDS ]; do

 

         if [ ! checkStopRunning ];then

            if [ ! checkRunning ]; then

               echo " FINISHED"

               FOUND="1"

            fi

            break

         fi

 

         if (checkRunning);then

            sleep 1

            printf  "."

         else

            echo " FINISHED"

            FOUND="1"

            break

         fi

         i=`expr $i + 1`

       done

       if "$FOUND" -ne "1" ];then

         echo

         echo "INFO: Regular shutdown not successful,  sending SIGKILL to process with pid '$PID'"

         kill -KILL $PID

         RET="1"

       fi

    elif [ -f "$ACTIVEMQ_PIDFILE" ];then

       echo "ERROR: No or outdated process id in '$ACTIVEMQ_PIDFILE'"

       echo

       echo "INFO: Removing $ACTIVEMQ_PIDFILE"

    else

       echo "ActiveMQ not running"

       exit 0

    fi

    rm -f $ACTIVEMQ_PIDFILE >/dev/null 2>&1

    rm -f $ACTIVEMQ_DATA/stop.pid >/dev/null 2>&1

    exit $RET

}

 

# Invoke a task on a running ActiveMQ instance

#

# @RET  : 0 => successful

#         !0 => something went wrong

#

# Note: This function uses globally defined variables

# - $ACTIVEMQ_QUEUEMANAGERURL : The url of the queuemanager

# - $ACTIVEMQ_OPTS            : Additional options

# - $ACTIVEMQ_SUNJMX_START    : options for JMX settings

# - $ACTIVEMQ_SSL_OPTS        : options for SSL encryption

invoke_task(){

    # call task in java binary

    if ( checkRunning );then

      if "$1" "browse" ] && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then

         ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

         COMMANDLINE_ARGS="$1 $ACTIVEMQ_QUEUEMANAGERURL `echo $COMMANDLINE_ARGS|sed 's,^browse,,'`"

      elif "$1" "query" ]  && [ -n "$ACTIVEMQ_QUEUEMANAGERURL" ];then

         ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

         COMMANDLINE_ARGS="$1 $ACTIVEMQ_SUNJMX_CONTROL `echo $COMMANDLINE_ARGS|sed 's,^query,,'`"

      else

         ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SSL_OPTS"

         COMMANDLINE_ARGS="$COMMANDLINE_ARGS $ACTIVEMQ_SUNJMX_CONTROL"

      fi

      invokeJar

      exit $?

    else

      invokeJar

      exit 1

    fi

}

 

show_help() {

  invokeJar

  RET="$?"

  cat << EOF

Tasks provided by the sysv init script:

    restart         - stop running instance (if there is one), start new instance

    console         - start broker in foreground, useful for debugging purposes

    status          - check if activemq process is running

    setup           - create the specified configuration file for this init script

                      (see next usage section)

 

Configuration of this script:

    The configuration of this script can be placed on /etc/default/activemq or $HOME/.activemqrc.

    To use additional configurations for running multiple instances on the same operating system

    rename or symlink script to a name matching to activemq-instance-<INSTANCENAME>.

    This changes the configuration location to /etc/default/activemq-instance-<INSTANCENAME> and

    \$HOME/.activemqrc-instance-<INSTANCENAME>. Configuration files in /etc have higher precedence.

EOF

  exit $RET

}

 

# ------------------------------------------------------------------------

# MAIN

 

# show help

if [ -z "$1" ];then

 show_help

fi

 

case "$1" in

  status)

      invoke_status

    ;;

  restart)

    if ( checkRunning );then

      $0 stop

    fi

    $0 status

    $0 start

    $0 status

    ;;

  start)

    invoke_start

    ;;

  console)

    invoke_console

    ;;

  stop)

    invoke_stop

    ;;

  *)

    invoke_task

esac

一些参考:

1.init wikipedia https://en.wikipedia.org/wiki/Init

2.(重点)Operating system service management https://en.wikipedia.org/wiki/Operating_system_service_management

本文出自 “通信,我的最爱” 博客,请务必保留此出处http://dgd2010.blog.51cto.com/1539422/1680420

时间: 2024-10-03 18:16:37

Linux Shell之init脚本与activemq init脚本设计亮点分析的相关文章

面向 DBA 的 Linux Shell 脚本简介

http://www.itpub.net/showthread.php?s=&threadid=720028 面向 DBA 的 Linux Shell 脚本简介 7 年前,Oracle 发布了 Linux 上的第一个商业数据库.从那时起,Oracle.Red Hat 和 Novell/SUSE 就不断地合作更改 Linux 内核,从而提高数据库和应用程序的性能.正因为这样,用于 Linux 的 Oracle 数据库 10g 才包含了与操作系统紧密相关的许多增强功能.DBA 比以往任何时候更需要了

MySQL的一些功能实用的Linux shell脚本分享_Mysql

Memcached启动脚本 # vim /etc/init.d/memcached #!/bin/bash #======================================================================================= # chkconfig: - 80 12 # description: Distributed memory caching daemon # processname: memcached #===========

思维导图学 Linux Shell攻略之干货篇 mysql数据库脚本管理系统

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dba10g.blog.51cto.com/764602/1610653 以结果为导向的学习,才是最有效率学习.笔者以前也曾经隔三差五的学习linux shell编程来着.给我的感觉就是,今天学了,后天忘了,一星期之后就白学了. 还好,最近自己平时没啥事,一直照着<linux shell攻略>,学做一些小例子,看着自己写的shell程序,简单的几行程序,实现一些好玩的效果,信心

linux shell rman备份文件的脚本

rman备份脚本 #! /bin/bash su - oracle <<! rman target /<<EOF backup AS COMPRESSED BACKUPSET database include current controlfile format'/orabak/db_%d_%T_%s' plus archivelog format'/orabak/arch_%d_%T_%s' delete allinput; delete noprompt obsolete; e

Linux shell脚本基础学习详细介绍(完整版)

Linux shell脚本基础学习这里我们先来第一讲,介绍shell的语法基础,开头.注释.变量和 环境变量,向大家做一个基础的介绍,虽然不涉及具体东西,但是打好基础是以后学习轻松地前提. 1. Linux 脚本编写基础 ◆1.1 语法基本介绍1.1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执行该脚本,还必须使其可执行. 要使脚本可

Linux Shell脚本查看NUMA信息

  这篇文章主要介绍了Linux Shell脚本查看NUMA信息,本文直接给出脚本实现代码,需要的朋友可以参考下 Nova在NFV场景下会提供NUMA相关高级特性,这里提供一个脚本查看计算节点的NUMA相关信息. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Linux Shell脚本系列教程(一):Shell入门

  这篇文章主要介绍了Linux Shell脚本系列教程(一):Shell入门,本文讲解了Shell简介.Shell基本操作.如何打开Shell终端.Shell脚本的概念.如何运行Shell脚本.Shell脚本的注释等基础知识,需要的朋友可以参考下 一.Shell简介 诸多类Unix操作系统的设计令人惊叹.即便是在数十年后的今天,Unix式的操作系统架构仍是有史以来最佳的设计之一.这种架构最重要的一个特性就是命令行界面或者shell.shell环境使得用户能与操作系统的核心功能进行交互.术语脚本

Linux Shell脚本系列教程(二):终端打印命令详解

  这篇文章主要介绍了Linux Shell脚本系列教程(二):终端打印命令详解,本文着重讲解了echo终端打印.printf终端打印两个打印出输出命令,需要的朋友可以参考下 终端打印 终端是交互式工具,用户可以通过它与shell环境进行交互.在终端中打印文本是大多数shell脚本和工具日常需要执行的基本任务.通过终端打印,人们可以知道系统的运行状态,这对用户来说是至关重要的. echo终端打印 代码如下: echo "Welcome to Bash" echo 'Welcome to

Linux Shell脚本系列教程(三):变量和环境变量

  这篇文章主要介绍了Linux Shell脚本系列教程(三):变量和环境变量,本文讲解了普通变量.获取字符串的长度.环境变量等内容,需要的朋友可以参考下 一.玩转变量和环境变量 变量是任何一种编程语言都必不可少的组成部分,用于存放各种类型的变量.脚本语言大多是弱类型语言(动态语言),也就是说在使用变量时,不需要事先声明变量的类型,只需要直接赋值就可以.在Bash中,每一个变量的值都是字符串.无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储.有一些特殊的变量会被shell环境和操作系统