实习日志(第六周2)

本文详细介绍了 Jenkins 的几个常用插件,包括 Subversion Plugin 的后提交钩子功能,Kerberos SSO 插件的用户认证机制,CloudBees Folders Plugin 对项目组织的管理,Promoted Builds 插件如何区分优质构建,以及 Dingding Notification 和 Dingding Json Pusher 插件在构建通知和复杂消息推送中的应用。

jenkins常用插件补充

1. Subversion Plugin
  1. Jenkins可以拉取Subversion存储库进行更改,这只能发生在每分钟一次,所以您可能还需要等待一整分钟才能发现更改。为了减少这种延迟,可以设置一个后提交钩子,以便Subversion存储库可以在对该存储库进行更改时通知Jenkins。 为此,请将以下脚本放在您的后提交文件($ REPOSITORY / hooks目录)中:
REPOS="$1"
REV="$2"
UUID=`svnlook uuid $REPOS`
/usr/bin/wget \
  --header "Content-Type:text/plain;charset=UTF-8" \
  --post-data "`svnlook changed --revision $REV $REPOS`" \
  --output-document "-" \
  --timeout=2 \
  http://server/subversion/${UUID}/notifyCommit?rev=$REV
  # 请注意rev = $ REV参数,这告诉Jenkins准确检查挂钩报告的修订版本。 如果您的工作有多个Subversion模块位置定义,这可能导致检出不一致 - 所以建议在这种情况下不要使用'?rev = $ REV'。
  ```
  如果您的Jenkins使用“防止跨站点请求伪造攻击”安全选项,则上述请求将被拒绝403错误(“未包含有效碎屑”)。 该请求中需要的碎屑可以从URL http:// server / crumbIssuer / api / xml(或/ api / json)获取。 这可以包含在上面的wget调用中,如下所示:
  ```
  --header `wget -q --output-document - \
  'http://server/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'`
  ```
  由于wget默认情况下重试次数不超过给定超时时间为20次,所以在慢速SVN服务器上的--timeout = 2可能会导致Jenkins扫描存储库多次,进一步减缓SVN服务器一段时间后,使詹金斯没有反应。
  此问题的可能解决方案是增加超时时间,使用参数-retries = 3添加更低的最大重试次数,或者通过添加2>&1&last而使wget调用异步(从而忽略任何通信错误) wget调用。超时太低可能导致您的提交挂起并抛出502错误,如果您在代理后面,或提交后错误,如果没有。 增加超时,直到不再看到wget重试。
  ```
  #!/bin/sh
  REPOS="$1"
  REV="$2"

  # No environment is passed to svn hook scripts; set paths to external tools explicitly:
  WGET=/usr/bin/wget
  SVNLOOK=/usr/bin/svnlook

  # If your server requires authentication, it is recommended that you set up a .netrc file to store your username and password
  # Better yet, since Jenkins v. 1.426, use the generated API Token in place of the password
  # See https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients
  # Since no environment is passed to hook scripts, you need to set $HOME (where your .netrc lives)
  # By convention, this should be the home dir of whichever user is running the svn process (i.e. apache)
  HOME=/var/www/

  UUID=`$SVNLOOK uuid $REPOS`
  NOTIFY_URL="subversion/${UUID}/notifyCommit?rev=${REV}"
  CRUMB_ISSUER_URL='crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'

  function notifyCI {
    # URL to Hudson/Jenkins server application (with protocol, hostname, port and deployment descriptor if needed)
    CISERVER=$1

    # Check if "[X] Prevent Cross Site Request Forgery exploits" is activated
    # so we can present a valid crumb or a proper header
    HEADER="Content-Type:text/plain;charset=UTF-8"
    CRUMB=`$WGET --auth-no-challenge --output-document - ${CISERVER}/${CRUMB_ISSUER_URL}`
    if [ "$CRUMB" != "" ]; then HEADER=$CRUMB; fi

    $WGET \
        --auth-no-challenge \
        --header $HEADER \
        --post-data "`$SVNLOOK changed --revision $REV $REPOS`" \
        --output-document "-"\
        --timeout=2 \
        ${CISERVER}/${NOTIFY_URL}
  }

  # The code above was placed in a function so you can easily notify multiple Jenkins/Hudson servers:
  notifyCI "http://myPC.company.local:8080"
  notifyCI "http://jenkins.company.com:8080/jenkins"
  ```
  如果您的服务器上启用了上述脚本,则会处理“防止跨站点请求伪造漏洞”选项。 如果您没有启用该选项,额外的wget调用是无害的,但如果您不需要,可随意删除它。 上述脚本还要求您将运行subversion的用户的主目录中的.netrc文件设置为(svnserve进程或httpd)。 有关.netrc文件语法的更多信息,请看这里。 上面的脚本可以轻松地向多个Jenkins服务器通知相同的SVN提交。 如果你有一个.netrc文件,即使他们有不同的管理用户设置,它也很容易。 如果您不想混淆.netrc文件,您可以在文件中硬编码用户和密码(或API Token)信息,并将--username = user和--password =“pass”标志添加到 wget调用。

#### 2. Jenkins Master/Slave架构
1. 当自动化测试用例需要在多个PC机或虚拟机中执行时,如果在每个虚拟机中均搭建类似tomcat+jenkins的环境,将会造成例如每台虚拟机资源占用大、对环境的配置维护成本大等弊端,此时,就可以采用Jenkins分布式构建方式了。<br>
远程工作目录:指定远程中的节点机器的工作目录,即Job中checkout出的代码所在的workspace目录<br>
标签:该节点的唯一标识,当在Job中要指定只在该节点进行构建与测试时,通过该唯一标识进行指定
1. Jenkins slave开机自启动
  1. 若要对所用用户均进行开机自启动,则将.bat启动文件的快捷方式放入 ‘\Documents and Settings\All Users\“开始”菜单\程序\启动’目录下
  1. 若只要对指定用户进行开机自启动,则将.bat启动文件的快捷方式放入 ‘\Documents and Settings\ <用户名字>\“开始”菜单\程序\启动’目录下
1. Jenkins节点监控
jenkins节点由于系统运行、网络环境等各种因素,难免会出现系统挂机、节点掉线等情况,因此要想及时发现这些情况,就需要对节点进行监控,
可以采用这里推荐的监控并重连机制:https://wiki.jenkins-ci.org/display/JENKINS/Monitor+and+Restart+Offline+Slaves
  1. 由于jenkins节点监控使用的是groovy脚本调用的jenkins内部api,因此需要先安装groovy plugin插件
  1. 在Master中新建一个名字为如monitor的job,设置为例如每30分钟运行一次。
  1. 新增Excute system Groovy script构建步骤:
<span style="font-size: 13px;">import hudson.model.*  
import hudson.node_monitors.*  
import hudson.slaves.*  
import java.util.concurrent.*  
jenkins = Hudson.instance
import javax.mail.internet.*;  
import javax.mail.*  
import javax.activation.*  
def sendMail (slave, cause) {  
//这里使用的是参数化构建中的变量,如果不使用此方式,可以注释掉,而使用下面的toAddress  
toAddress = build.buildVariableResolver.resolve("EMAIL_RECEIVERS")  
message = slave + " slave is down. Check http://192.168.10.181:8080/jenkins/computer/" + slave + "\nBecause " + cause  
subject = "【jenkins节点监控】" + slave + " slave is offline"  
//toAddress = "***@***.com;***@***.com"  
fromAddress = "***@***.com"  
host = "SMTP_SERVER"  
port = "SMTP_PORT"  
Properties props = new Properties();  
// 发送邮件的服务器  
props.setProperty("mail.smtp.host", "smtp.***.com");  
// 发送邮件的协议  
props.setProperty("mail.transport.protocol", "smtp");  
// 在连接服务器的时候是否需要验证,发邮件是需要验证的  
props.setProperty("mail.smtp.auth", "true");  
// 当需要进行验证的时候,会自动从Session中去取该Authenticator对象  
Authenticator authenticator = new Authenticator() {  
@Override  
protected PasswordAuthentication getPasswordAuthentication() {  
 return new PasswordAuthentication("your user name", "your passwd"); //输入用户名、密码  
}  
};  
Session lSession = Session.getInstance(props,authenticator);  
MimeMessage msg = new MimeMessage(lSession);  
//tokenize out the recipients in case they came in as a list  
StringTokenizer tok = new StringTokenizer(toAddress,";");  
ArrayList emailTos = new ArrayList();  
while(tok.hasMoreElements()){  
emailTos.add(new InternetAddress(tok.nextElement().toString()));  
}  
InternetAddress[] to = new InternetAddress[emailTos.size()];  
to = (InternetAddress[]) emailTos.toArray(to);  
msg.setRecipients(MimeMessage.RecipientType.TO,to);  
InternetAddress fromAddr = new InternetAddress(fromAddress);  
msg.setFrom(fromAddr);  
msg.setFrom(new InternetAddress(fromAddress));  
msg.setSubject(subject);  
msg.setText(message)  
Transport transporter = lSession.getTransport("smtp");  
transporter.connect();  
transporter.send(msg);  
}  
def getEnviron(computer) {  
def env  
def thread = Thread.start("Getting env from ${computer.name}", { env = computer.environment })  
thread.join(2000)  
if (thread.isAlive()) thread.interrupt()  
env  
}  

def slaveAccessible(computer) {  
getEnviron(computer)?.get('PATH') != null  
}  
def numberOfflineNodes = 0  
def numberNodes = 0  
for (slave in jenkins.slaves) {  
def computer = slave.computer  
numberNodes ++  
println ""  
println "Checking computer ${computer.name}:"  
def isOK = (slaveAccessible(computer) && !computer.offline)  
if (isOK) {  
 println "\t\tOK, got PATH back from slave ${computer.name}."  
 println('\tcomputer.isOffline: ' + slave.getComputer().isOffline());   
 println('\tcomputer.isTemporarilyOffline: ' + slave.getComputer().isTemporarilyOffline());  
 println('\tcomputer.getOfflineCause: ' + slave.getComputer().getOfflineCause());  
 println('\tcomputer.offline: ' + computer.offline);
} else {  
 numberOfflineNodes ++  
 println "  ERROR: can't get PATH from slave ${computer.name}."  
 println('\tcomputer.isOffline: ' + slave.getComputer().isOffline());   
 println('\tcomputer.isTemporarilyOffline: ' + slave.getComputer().isTemporarilyOffline());  
 println('\tcomputer.getOfflineCause: ' + slave.getComputer().getOfflineCause());  
 println('\tcomputer.offline: ' + computer.offline);   
 sendMail(computer.name, slave.getComputer().getOfflineCause().toString())  
 if (slave.getComputer().isTemporarilyOffline()) {  
  if (!slave.getComputer().getOfflineCause().toString().contains("Disconnected by")) {  
     computer.setTemporarilyOffline(false, slave.getComputer().getOfflineCause())          
  }  
 } else {  
     computer.connect(true)    
 }  
}  
}  
println ("Number of Offline Nodes: " + numberOfflineNodes)  
println ("Number of Nodes: " + numberNodes)  </span><span style="font-size:14px;">  
</span>

“`

3. Kerberos SSO 插件
  1. 该插件读取用户的Kerberos票证并使用它将用户记录到Jenkins。 它可以与Active Directory插件一起很好地使用。 它还可以重定向在请求中忽略指定域的用户。
  2. 可以通过在请求中设置Bypass-Kerberos头来绕过特定请求的身份验证。 它的价值无关紧要,用户将被认证为匿名的。
  3. 插件可以被配置为允许未经身份验证的请求,并且只有在请求时进行身份验证。 否则,将为每个请求执行身份验证。
    jenkins上进入系统管理>系统配置中进行配置
    kerberos1.png
    在linux服务器上安装指南:

    1. krb5.conf的位置默认为“/etc/krb5.conf”。此外,如果用户在该字段中输入其他信息,并且在该位置找不到该文件,它将返回到“/etc/krb5.conf”以查找该文件。libdefaults部分告诉Spnego在领域中使用哪种加密类型,而领域告诉Spnego密钥分配中心所在的位置。 提供的Kerberos票证的请求被发送到该服务器。Jenkins已读取这个文件的权限是非常重要的!

      [libdefaults]
      default_realm = INTERNALDOMAIN.NET
      default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
      default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
      preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
      
      [realms]
      INTERNALDOMAIN.NET = {
        kdc = 59.169.100.36
        kdc = 7b99:a413:0:ac1b::00:01
        kdc = 7b99:a413:0:ac1b::00:02
        kdc = 7b99:a413:0:ac1b::00:03
      }
    2. Login.conf的位置是设置中最重要的部分,而且是最复杂的。 如果这是错误的指定,Jenkins将立即告诉你一个Servlet异常。 它必须指向名为“login.conf”的服务器上的文件,或通常在文档等中指定“jaas.conf”。 与“krb5.conf”文件一样,Jenkins对此文件的读取权限非常重要!

      Kerberos {
      com.sun.security.auth.module.Krb5LoginModule required
      principal="HTTP/hostname01@INTERNALDOMAIN.NET"
      doNotPrompt="false"
      useTicketCache="false"
      useKeyTab="true"
      keyTab="/etc/krb5.keytab";
      };
      
      spnego-client {
      com.sun.security.auth.module.Krb5LoginModule required;
      };
      
      spnego-server {
      com.sun.security.auth.module.Krb5LoginModule required
      isInitiator="false"
      useKeyTab="true"
      keyTab="/etc/krb5.keytab"
      principal="HTTP/hostname01@INTERNALDOMAIN.NET"
      tryFirstPass="true"
      storePass="true"
      storeKey="true";
      };
      
      com.sun.security.jgss.initiate {
      com.sun.security.auth.module.Krb5LoginModule required
      principal="HTTP/hostname01@INTERNALDOMAIN.NET"
      useKeyTab="true"
      keyTab="/etc/krb5.keytab";
      };
      
      com.sun.security.jgss.accept {
      com.sun.security.auth.module.Krb5LoginModule required
      principal="HTTP/hostname01@INTERNALDOMAIN.NET"
      useKeyTab="true"
      keyTab="/etc/krb5.keytab";
      };
    3. Jenkins对keytab文件的读取权限非常重要!设置服务器时,可能需要在服务器上修改此keytab文件:

      
      # Write the following into a terminal:
      
      
      sudo net ads keytab list
      
      
      # If the server is correctly set up, it the keytab will contain rows looking something like this: HTTP/HOSTNAME01@INTERNALDOMAIN.NET
      
      
      
      # The important part here is the HTTP principal. If it doesn't contain such a row, type the following:
      
      
      sudo net ads keytab add \-P HTTP
      
      
      # Verify with the list command that the keytab now contains HTTP entries.
      

    要注意的一个重要事情是,您的servlet容器(例如Tomcat)需要具有足够的头部大小。 这种情况因环境而异,当事情似乎错误时,并不总是容易发现问题.

4. CloudBees Folders Plugin
  1. 随着项目和团队的数量的增加,Jenkins的相应数量的工作也会增加。 用户发现他们需要组织他们的项目和工作,使他们的管理更容易。 詹金斯不提供内置的功能来满足这一需求。
  2. CloudBees Folders 插件允许您将作业组织到分层文件夹中,就像在文件系统目录中组织文件一样。 这可以让您将相关作业组合在一起,然后可以对特定文件夹中的部门,项目和作业进行分组。 文件夹还可以定义内部作业可见的属性,使您能够简化分支和/或工作流管理。
  3. CloudBees Folders 插件允许您在每个文件夹的基础上设置安全权限(基于角色的访问控制插件)。 角色可以在嵌套文件夹层次结构中继承(或过滤掉)。 例如:工程部门文件夹可以给予所有工程师广泛的权限,但项目Foo子文件夹只允许某些工程师进行修改。
  4. 文件夹然后允许您快速完整地克隆一个文件夹与其子文件夹。
  5. 文件夹是命名空间感知的。 因此,您可以拥有位于不同层级下的相同名称的作业。
5. Promoted Builds插件
  1. 这个插件允许您通过引入promotion“促销”的概念来区分好的构建和坏的构建。简单地说,如果Promoted Builds通过了额外的标准(例如设置为下游作业的更全面的测试)则是一个成功的构建。
  2. 您使用Promoted的典型情况是有多个“测试”作业挂接为“构建”作业的下游作业。
  3. 然后,您将配置构建作业,以便在所有测试作业成功传递时升级构建。这允许您保持构建作业运行速度快(以便开发人员在构建失败时获得更快的反馈),并且您仍然可以与构建编译运行的问题进行区分。
  4. 在构建配置时勾选这个选项
    promoted_builds1.png
  5. promoted builds的例子
    1. 工件存储 - 您可能不想在每个版本上将工件推送到您的主要工件存储库。通过构建促销,只有当工件符合某些标准时,才能推送。例如,您可能只想在运行集成测试后推送它。
    2. Manual Promotions(手动 promotion) - 您可以选择一组可以运行Manual Promotions的人。 这样做可以在构建系统中进行“注销”。 例如,开发人员可以验证一个构建,并且只有在完全完成了工作产品时才批准它进行质量检查。 那么可以再增加一个promotion活动来进行质量保证。
    3. 工件的聚合 - 如果您有一个软件版本由几个不直接相关的工件组成,这些工件位于单独的作业中,则可能需要将经过验证的质量的所有工件聚合到分发位置。 要做到这一点,您可以创建一个新的作业,为每个要聚合的项目添加“从另一个作业复制工件”(可通过“复制工件插件”获得))。要获得一定的升级,请在副本中选择“使用固定链接” 工件步骤,则您的promoted builds应显示在要复制的项目列表中。
6. Dingding Notification 插件

允许用户通过Dingding-钉钉发送构建通知
1. 在钉钉创建一个钉钉机器人
dingding1.png
1. 安装插件后,每个作业都可以添加一个后期制作步骤,选择’叮当通知配置’
dingding2.png
dingding3.png

7. Dingding Json Pusher插件
  1. 允许用户将存储在JSON文件中的复杂消息推送到多个Dingding组。
  2. Dingding支持的任何格式消息都可以由此插件推送。
  3. 支持Jenkins管道。
  4. 支持Jenkins工作DSL。
参考资料中仅提供了前端开发实习工作周报和关于Unity3D的初步学习研究周记,未涉及软件开发实习14周的日志与周记相关内容,无法直接给出软件开发实习14周的日志与周记。不过可以参考已有的周报示例,推测软件开发实习日志与周记可能包含的内容。 如前端开发实习工作周报包含本周学习的知识(React基础知识和语法、HTML5和CSS3基础知识)、工作内容(为野牛期货客户端加入指标弹窗功能)以及遇到的问题(指标持久化存在问题) [^3]。关于Unity3D的初步学习研究周记包含学习过程(安装软件、创建工程和场景等)以及对软件中文件存放规则的介绍 [^4]。 以下为一份软件开发实习14周日志与周记的示例框架: ### 第1 - 2日志:熟悉公司开发环境,了解软件开发项目的整体架构和业务需求,学习公司内部使用的开发工具和规范。 周记:总结前两周对开发环境和项目的了解情况,记录学习开发工具过程中遇到的困难及解决方法。 ### 第3 - 4周 日志:参与项目的模块设计,与团队成员讨论技术方案,开始编写代码实现部分功能。 周记:汇报模块设计的思路和成果,分享代码编写过程中的经验和问题,如代码优化和调试的情况。 ### 第5 - 6周 日志:对已完成的代码进行测试,修复发现的bug,与测试人员沟通协调,确保代码质量。 周记:总结代码测试的结果和问题,分析bug产生的原因,提出改进措施。 ### 第7 - 8周 日志:参与项目的集成工作,将各个模块进行整合,处理模块之间的接口问题。 周记:汇报集成工作的进展和遇到的挑战,如接口兼容性问题的解决办法。 ### 第9 - 10周 日志:对项目进行性能优化,分析代码的性能瓶颈,采取相应的优化策略。 周记:总结性能优化的效果和经验,分享性能分析工具的使用方法。 ### 第11 - 12日志:协助团队进行项目的部署和上线工作,处理上线过程中出现的问题。 周记:汇报项目部署和上线的情况,记录上线过程中的问题和解决方案。 ### 第13 - 14周 日志:对整个实习期间的工作进行总结和回顾,整理项目文档,与团队成员交流实习心得。 周记:全面总结14周的实习工作,分享自己在技术和团队协作方面的成长和收获,对未来的软件开发工作提出展望。 ### 示例代码(以Python简单的功能实现为例) ```python # 一个简单的加法函数示例 def add_numbers(a, b): return a + b result = add_numbers(3, 5) print(result) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值