開発
Configuring Jenkins on OS X Mountain Lion
denvazh
Why?
In normal working software development environment, where certain tools used to make developers live easier (IDE, version control, doxygen and etc. ) there is a solution, that really helps controlling the how process. This is called continuous integration. Central part of such solution is a system for automated software testing and building. In this blog post I will explain how to setup Jenkins build system on OS X Mountain Lion environment.
Requirements
- preinstalled Xcode with command-line tools
- ALL actions below must be done either as a root user or sudo, so please make sure you have necessary admin permissions on the system you about to install software to.
1. Install homebrew
It is pretty straight-forward, thus I would recommend to follow offical installation documents provided here
Make sure to check if paths are in the following order
echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/X11/bin
If its not the case, then change the file /etc/paths to be like
/usr/local/bin /usr/bin /bin /usr/local/sbin /usr/sbin /sbin
Important: creating text file in /etc/paths.d won’t have any effect, because paths from /etc/paths loaded first, and only then paths from files in /etc/paths.d.
2. Install jenkins
Installing jenkins with homebrew
brew install jenkins
Creating jenkins user.
#!/bin/bash # Modified by Denis Vazhenin <[email protected]> # # Based on original script for jenkins post install on OS X # https://github.com/yokoe/jenkins/blob/master/osx/scripts/postinstall-launchd-jenkins # checking if platform is OS X if [ `uname -s` != 'Darwin' ]; then printf "Error: this script can be used only in OS X\n" exit 1 fi JENKINS_USR='jenkins' JENKINS_HOMEDIR="/Users/Shared/Jenkins" JENKINS_HOME="/Users/Shared/Jenkins/Home" mkdir -p $JENKINS_HOMEDIR mkdir -p $JENKINS_HOME # check if user already exists stat=`dscl . -list /Users/${JENKINS_USR} 2&>1` if [ $stat -eq 0 ]; then # user already exists printf "User %s already exists \n" $JENKINS_USR # forcing shell not to be /usr/bin/false dscl . -change /Users/${JENKINS_USR} UserShell /usr/bin/false /bin/bash else # user not exists printf "Creating %s user\n" $JENKINS_USR # find not occupied system uid (<500) uid=$(dscl . -list /Users uid | sort -nrk 2 | awk '$2 < 500 {print $2 + 1; exit 0}') if [ $uid -eq 500 ]; then printf "Error: Unable to create %s user, all uid < 500 already occupied" exit 1 fi # group should be the same as uid, looking for gid gid=$uid while dscl . -search /Groups gid $gid | grep -q $gid; do gid=$(($gid + 1)) __stat=$(dscl . -search /Users uid $gid | grep $gid) if [ x"${__stat}" == x ]; then # "$gid is free" uid=$gid fi done printf "Using %s:%s for %s user\n" $uid $gid $JENKINS_USR # create user ( use dscl cmd ) dscl . -create /Groups/${JENKINS_USR} PrimaryGroupID $gid dscl . -create /Users/${JENKINS_USR} UserShell /bin/bash dscl . -create /Users/${JENKINS_USR} Password '*' dscl . -create /Users/${JENKINS_USR} UniqueID $uid dscl . -create /Users/${JENKINS_USR} PrimaryGroupID $gid dscl . -create /Users/${JENKINS_USR} NFSHomeDirectory "$JENKINS_HOMEDIR" dscl . -append /Groups/${JENKINS_USR} GroupMembership ${JENKINS_USR} fi # fix directory permissions find "$JENKINS_HOMEDIR" \( -not -user ${JENKINS_USR} -or -not -group ${JENKINS_USR} \) -print0 | xargs -0 chown ${JENKINS_USR}:${JENKINS_USR} # create directory for logs and fix permissions mkdir -p /var/log/${JENKINS_USR} chown ${JENKINS_USR}:${JENKINS_USR} /var/log/${JENKINS_USR} printf "Done.\n"
Setting-up jenkins service default parameters
defaults write /Library/Preferences/org.jenkins-ci war "/usr/local/opt/jenkins/libexec/jenkins.war" defaults write /Library/Preferences/org.jenkins-ci heapSize 512m defaults write /Library/Preferences/org.jenkins-ci httpListenAddress 127.0.0.1 defaults write /Library/Preferences/org.jenkins-ci httpPort 8080 defaults write /Library/Preferences/org.jenkins-ci permGen 256m defaults write /Library/Preferences/org.jenkins-ci JENKINS_HOME "/Users/Shared/Jenkins/Home"
Setting-up jenkins service wrapper. Put the following script to /Library/Application Support/Jenkins/jenkins-runner.sh
#!/bin/bash # # Startup script used by Jenkins launchd job. # Mac OS X launchd process calls this script to customize # the java process command line used to run Jenkins. # # Customizable parameters are found in # /Library/Preferences/org.jenkins-ci.plist # # You can manipulate it using the "defaults" utility. # See "man defaults" for details. defaults="defaults read /Library/Preferences/org.jenkins-ci" war=`$defaults war` || war="/Applications/Jenkins/jenkins.war" javaArgs="" heapSize=`$defaults heapSize` && javaArgs="$javaArgs -Xmx${heapSize}" permGen=`$defaults permGen` && javaArgs="$javaArgs -XX:MaxPermSize=${permGen}" home=`$defaults JENKINS_HOME` && export JENKINS_HOME="$home" add_to_args() { val=`$defaults $1` && args="$args --${1}=${val}" } args="" add_to_args prefix add_to_args httpPort add_to_args httpListenAddress add_to_args httpsPort add_to_args httpsListenAddress add_to_args ajp13Port add_to_args ajp13ListenAddress echo "JENKINS_HOME=$JENKINS_HOME" echo "Jenkins command line for execution:" echo /usr/bin/java $javaArgs -jar "$war" $args exec /usr/bin/java $javaArgs -jar "$war" $args
Installing and enabling jenkins service.
Put the following script and name it as /Library/LaunchAgents/org.jenkins-ci.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>StandardOutPath</key> <string>/var/log/jenkins/jenkins.log</string> <key>StandardErrorPath</key> <string>/var/log/jenkins/jenkins.log</string> <key>EnvironmentVariables</key> <dict> <key>JENKINS_HOME</key> <string>/Users/Shared/Jenkins/Home</string> </dict> <key>GroupName</key> <string>daemon</string> <key>KeepAlive</key> <true/> <key>Label</key> <string>org.jenkins-ci</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/Library/Application Support/Jenkins/jenkins-runner.sh</string> </array> <key>RunAtLoad</key> <true/> <key>UserName</key> <string>jenkins</string> <key>SessionCreate</key> <true /> </dict> </plist>
Fix ownership to root and permissions to 644.
PLIST='/Library/LaunchAgents/org.jenkins-ci.plist'; chown root:wheel $PLIST && chmod 644 $PLIST
Start jenkins service
launchctl load -w /Library/LaunchAgents/org.jenkins-ci.plist
3. Install nginx
Installing nginx with homebrew
brew install nginx
Configure nginx to run as a system daemon
cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist /Library/LaunchAgents/ chown root:wheel /Library/LaunchAgents/homebrew.mxcl.nginx.plist && chmod 644 /Library/LaunchAgents/homebrew.mxcl.nginx.plist
Configure jenkins to run behind nginx reverse proxy
Edit file /usr/local/etc/nginx/nginx.conf to be like this, but MAKE SURE TO CHANGE server_name to match YOUR settings.
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name some_jenkins_server.com; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 150; proxy_send_timeout 100; proxy_read_timeout 100; proxy_buffers 4 32k; client_max_body_size 8m; client_body_buffer_size 128k; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
Check configuration and start nginx
/usr/local/bin/nginx -t nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx
launchctl load -w /Library/LaunchAgents/homebrew.mxcl.nginx.plist
After few seconds if you go to some_jenkins_server.com (or the one you’ve set up yourself), you should see jenkins menu.
Conclusion
From that point it is possible to setup jenkins in the way it is desired for any software development team. Security, build settings, automatic deployment to external services and etc. Whole world of continuos integration is open for you.
One more thing: why I thought it would be better to have a setup like this? Answer is very simple: jenkins is very well maintained and regularly updated, thus (from my point of view) it is good to use existing tools, namely homebrew, to install and update it.