websphere 8.5启动wsadmin.sh失败问题解决过程

第一次尝试启动 wsadmin.sh 失败,console提示错误:

WASX7093I: Issuing message: "WASX7011E: Cannot find file "$(was.install.root)/bin/securityProcs.jacl""
WASX7093I: Issuing message: "WASX7011E: Cannot find file "$(was.install.root)/bin/LTPA_LDAPSecurityProcs.jacl""
WASX7093I: Issuing message: "WASX7023E: Error creating "SOAP" connection to host "localhost"; exception information: com.ibm.websphere.management.exception.ConnectorNotAvailableException: [SOAPException: faultCode=SOAP-ENV:Client; msg=Error parsing HTTP status line "": java.util.NoSuchElementException; targetException=java.lang.IllegalArgumentException: Error parsing HTTP status line "": java.util.NoSuchElementException]"

是路径无法转换的错误,故将其配置为固定路径,修改/opt/IBM/ODM85/WAS/AppServer/properties/wsadmin.properties文件,将以下配置:

com.ibm.ws.scripting.traceFile=$(was.install.root)/logs/wsadmin.traceout
com.ibm.ws.scripting.profiles=$(was.install.root)/bin/securityProcs.jacl;$(was.install.root)/bin/LTPA_LDAPSecurityProcs.jacl

修改为:

com.ibm.ws.scripting.traceFile=/opt/IBM/ODM85/WAS/AppServer/logs/wsadmin.traceout
com.ibm.ws.scripting.profiles=/opt/IBM/ODM85/WAS/AppServer/bin/securityProcs.jacl;/opt/IBM/ODM85/WAS/AppServer/bin/LTPA_LDAPSecurityProcs.jacl

再次执行swadmin.sh,还是提示Error creating “SOAP” connection to host “localhost”,查看wsadmin.traceout发现找不到ssl.client.props文件的错误:

[10/16/14 22:58:22:452 CST] 00000001 SSLConfigMana E   CWPKI0019E: Error parsing the SSL client configuration file file:/opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/ssl.client.props.  The error returned is java.io.FileNotFoundException:file:/opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/ssl.client.props.

经查找(find -name ssl.client.props)WAS下有很多模版文件,拷贝一个ssl.client.props文件到对应目录:

cp /opt/IBM/ODM85/WAS/AppServer/profiles/odm850/temp/ssl.client.props /opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/

再次执行swadmin.sh,提示以下错误:

WASX7246E: Cannot establish "SOAP" connection to host "localhost" because of an authentication failure. Ensure that user and password are correct on the command line or in a properties file.
Exception message (if any): "ADMC0035E: No user name has been specified to create a secure SOAP administrative client."

查看wsadmin.traceout发现是因为找不到soap.client.props文件:

[10/17/14 0:34:00:528 CST] 00000001 AdminClientFa W   ADMC0046W: The system failed to load properties from com.ibm.SOAP.configURL: file:/opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/soap.client.props

同样查找(find -name soap.client.props)WAS下有很多模版文件,拷贝一个soap.client.props文件到对应目录:

cp /opt/IBM/ODM85/WAS/AppServer/profiles/odm850/temp/soap.client.props /opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/

再次执行swadmin.sh,提示以下权限不足的错误:

Exception message (if any): "ADMN0022E: Access is denied for the getProcessType operation on Server MBean because of insufficient or empty credentials."

修改/opt/IBM/ODM85/WAS/AppServer/profiles/odm850/properties/soap.client.props文件,设置帐号密码:

com.ibm.SOAP.loginUserid=admin
com.ibm.SOAP.loginPassword=password

再次执行swadmin.sh,登录成功:

WASX7209I: Connected to process "server1" on node localhostNode01 using SOAP connector;  The type of process is: UnManagedProcess
WASX7029I: For help, enter: "$Help help"
wsadmin>

Reference:
1. ssl.client.props client configuration file,http://www-01.ibm.com/support/knowledgecenter/api/content/SSCKBL_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/rsec_sslclientpropsfile.html
2. Using the Administration Thin Client,http://www-01.ibm.com/support/knowledgecenter/SSCKBL_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/txml_adminclient.html

httpd2.4和2.2在访问控制配置的差异

2.2版本访问控制是通过Order, Allow, Deny, 和Satisfy这几个指令,对客户端访问hostname、IP以及其他requests信息进行限制.
2.4版本使用mod_authz_host模块以类似权限检查的方式进行访问控制。旧的访问控制方式应该改用新的机制。但2.4版本也提供一个新的mod_access_compat模块来适应旧的配置方式。



以下列出几个2.2和2.4配置差异例子:

禁止所有请求:
2.2 configuration:

Order deny,allow
Deny from all

2.4 configuration:

Require all denied


允许所有请求:
2.2 configuration:

Order allow,deny
Allow from all

2.4 configuration:

Require all granted


仅允许example.org域可访问:
2.2 configuration:

Order Deny,Allow
Deny from all
Allow from example.org

2.4 configuration:

Require host example.org


参考:https://httpd.apache.org/docs/2.4/upgrading.html

日志

Shell语法中的管道符命令“|”,用于将前一个命令的输出作为紧接其后命令的输入。如果将其用好了,一行指令可以实现一些很强大的功能。

1. 查找指定内容:
于管道符命令“|”后接grep命令,在前一个命令的输出中查找指定内容。

在所有进程中查找是否存在httpd进程:

> ps -ef | grep myapp
65534     4587  4586  1 22:41 pts/2    00:00:00 /opt/myapp/bin/myapp -config /opt/myapp/conf/myapp.conf
root      4612  4470  0 22:41 pts/2    00:00:00 grep myapp

在log日志中查找是否有ERROR信息(-n参数添加行号,这样可明确知道那一行有错误)

> cat -n myapp.log | grep ERROR

在log日志最开始10行内容查找是否有ERROR信息

> head -n 10 myapp.log | grep ERROR

在log日志最后10行内容查找是否有ERROR信息

> tail -n 10 myapp.log | grep ERROR

在log日志第10行之后的内容中查找是否有ERROR信息

> tail -n +10 myapp.log | grep ERROR

获得log中ERROR、WARN类型(除去INFO类型)的日志:

> cat myapp.log | grep -v ' INFO ' #INFO标记前后有空格,此命令也可以直接使用grep命令:grep -v ' INFO ' myapp.log

有时候一个目录下的文件太多,只想查看今天有更新异动的文件:

> ls -l |grep ' '$(date +%m-%d)
-rw-r--r-- 1 root root       5 09-24 22:59 myapp_out.log
-rw------- 1 root root    2211 09-24 22:41 myapp_err.log

2. 对内容进行操作:
获得所有进程的进程编号:

> ps aux | cut -c 9-15

获得当前目录文件的文件名列表:

> ls -l |cut -c 42-255

3. xarg命令
该命令功能有点类似管道符命令,它将多行内容转为一行内容,行与行之间用空格间隔,并此行内容作为参数传递给其他命令。

获得所有进程的进程编号并一行显示:

> ps aux | cut -c 9-15 | xargs echo

4. 经典应用案例:
将/opt/myapp目录下的程序的进程kill掉:

> ps aux | grep '/opt/myapp' | cut -c 9-15 | xargs kill -9

将今日有异动的log日志打包为一个zip档:

> ls -l |grep ' '$(date +%m-%d) | cut -c 43-255 | xargs zip log_$(date +%Y%m%d).zip

使用管道符组建功能强大的指令

Git远程操作详解

文章来源:http://www.ruanyifeng.com/blog/2014/06/git_remote.html

本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Git远程操作。

    - git clone
    - git remote
    - git fetch
    - git pull
    - git push

本文针对初级用户,从最简单的讲起,但是需要读者对Git的基本用法有所了解。同时,本文覆盖了上面5个命令的几乎所有的常用用法,所以对于熟练用户也有参考价值。

一、git clone
远程操作的第一步,通常是从远程主机克隆一个版本库,这时就要用到git clone命令。

$ git clone <版本库的网址>

比如,克隆jQuery的版本库。

$ git clone https://github.com/jquery/jquery.git

该命令会在本地主机生成一个目录,与远程主机的版本库同名。如果要指定不同的目录名,可以将目录名作为git clone命令的第二个参数。

$ git clone <版本库的网址> <本地目录名>

git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等,下面是一些例子。

$ git clone http[s]://example.com/path/to/repo.git/
$ git clone ssh://example.com/path/to/repo.git/
$ git clone git://example.com/path/to/repo.git/
$ git clone /opt/git/project.git
$ git clone file:///opt/git/project.git
$ git clone ftp[s]://example.com/path/to/repo.git/
$ git clone rsync://example.com/path/to/repo.git/

SSH协议还有另一种写法。

$ git clone [user@]example.com:path/to/repo.git/

通常来说,Git协议下载速度最快,SSH协议用于需要用户认证的场合。各种协议优劣的详细讨论请参考官方文档。

二、git remote
为了便于管理,Git要求每个远程主机都必须指定一个主机名。git remote命令就用于管理主机名。
不带选项的时候,git remote命令列出所有远程主机。

$ git remote
origin

使用-v选项,可以参看远程主机的网址。

$ git remote -v
origin  git@github.com:jquery/jquery.git (fetch)
origin  git@github.com:jquery/jquery.git (push)

上面命令表示,当前只有一台远程主机,叫做origin,以及它的网址。

克隆版本库的时候,所使用的远程主机自动被Git命名为origin。如果想用其他的主机名,需要用git clone命令的-o选项指定。

$ git clone -o jQuery https://github.com/jquery/jquery.git
$ git remote
jQuery

上面命令表示,克隆的时候,指定远程主机叫做jQuery。

git remote show命令加上主机名,可以查看该主机的详细信息。

$ git remote show <主机名>

git remote add命令用于添加远程主机。

$ git remote add <主机名> <网址>

git remote rm命令用于删除远程主机。

$ git remote rm <主机名>

git remote rename命令用于远程主机的改名。

$ git remote rename <原主机名> <新主机名>

三、git fetch
一旦远程主机的版本库有了更新(Git术语叫做commit),需要将这些更新取回本地,这时就要用到git fetch命令。

$ git fetch <远程主机名>

上面命令将某个远程主机的更新,全部取回本地。

默认情况下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

$ git fetch <远程主机名> <分支名>

比如,取回origin主机的master分支。

$ git fetch origin master

所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取。比如origin主机的master,就要用origin/master读取。

git branch命令的-r选项,可以用来查看远程分支,-a选项查看所有分支。

$ git branch -r
origin/master
$ git branch -a
* master
  remotes/origin/master

上面命令表示,本地主机的当前分支是master,远程分支是origin/master。

取回远程主机的更新以后,可以在它的基础上,使用git checkout命令创建一个新的分支。

$ git checkout -b newBrach origin/master

上面命令表示,在origin/master的基础上,创建一个新分支。

此外,也可以使用git merge命令或者git rebase命令,在本地分支上合并远程分支。

$ git merge origin/master
# 或者
$ git rebase origin/master

上面命令表示在当前分支上,合并origin/master。

四、git pull
git pull命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。它的完整格式稍稍有点复杂。

$ git pull <远程主机名> <远程分支名>:<本地分支名>

比如,取回origin主机的next分支,与本地的master分支合并,需要写成下面这样。

$ git pull origin next:master

如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

$ git pull origin next

上面命令表示,取回origin/next分支,再与当前分支合并。实质上,这等同于先做git fetch,再做git merge。

$ git fetch origin
$ git merge origin/next

在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动”追踪”origin/master分支。
Git也允许手动建立追踪关系。

git branch master --set-upstream-to origin/next

上面命令指定master分支追踪origin/next分支。

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

$ git pull origin

上面命令表示,本地的当前分支自动与对应的origin主机”追踪分支”(remote-tracking branch)进行合并。

如果当前分支只有一个追踪分支,连远程主机名都可以省略。

$ git pull

上面命令表示,当前分支自动与唯一一个追踪分支进行合并。

如果合并需要采用rebase模式,可以使用–rebase选项。

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

五、git push
git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

$ git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。
如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。

$ git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。

$ git push origin :master
# 等同于
$ git push origin --delete master

上面命令表示删除origin主机的master分支。

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。

$ git push origin

上面命令表示,将当前分支推送到origin主机的对应分支。

如果当前分支只有一个追踪分支,那么主机名都可以省略。

$ git push

如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push。

$ git push -u origin master

上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。

不带任何参数的git push,默认只推送当前分支,这叫做simple方式。此外,还有一种matching方式,会推送所有有对应的远程分支的本地分支。Git 2.0版本之前,默认采用matching方法,现在改为默认采用simple方式。如果要修改这个设置,可以采用git config命令。

$ git config --global push.default matching
# 或者
$ git config --global push.default simple

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。

$ git push --all origin

上面命令表示,将所有本地分支都推送到origin主机。

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用–force选项。

$ git push --force origin

上面命令使用–force选项,结果导致在远程主机产生一个”非直进式”的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用–force选项。

最后,git push不会推送标签(tag),除非使用–tags选项。

$ git push origin --tags

Git分支管理策略

文章来源:http://www.ruanyifeng.com/blog/2012/07/git.html

Git版本的分支(branch)和合并(merge)十分方便。有些传统的版本管理软件,分支操作实际上会生成一份现有代码的物理拷贝,而Git只生成一个指向当前版本(又称”快照”)的指针,因此非常快捷易用。但是,太方便了也会产生副作用。如果你不加注意,很可能会留下一个枝节蔓生、四处开放的版本库,到处都是分支,完全看不出主干发展的脉络。
Vincent Driessen提出了一个分支管理的策略,我觉得非常值得借鉴。它可以使得版本库的演进保持简洁,主干清晰,各个分支各司其职、井井有条。理论上,这些策略对所有的版本管理系统都适用,Git只是用来举例而已。如果你不熟悉Git,跳过举例部分就可以了。

一、主分支Master
首先,代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布。
Git主分支的名字,默认叫做Master。它是自动建立的,版本库初始化以后,默认就是在主分支在进行开发。

二、开发分支Develop
主分支只用来分布重大版本,日常开发应该在另一条分支上完成。我们把开发用的分支,叫做Develop。这个分支可以用来生成代码的最新隔夜版本(nightly)。如果想正式对外发布,就在Master分支上,对Develop分支进行”合并”(merge)。

Git创建Develop分支的命令:

git checkout -b develop master

切换到Master分支

git checkout master

对Develop分支进行合并到master分支,–no-ff参数是什么意思。默认情况下,Git执行”快进式合并”(fast-farward merge),会直接将Master分支指向Develop分支。

git merge --no-ff develop

三、功能(feature)分支:
它是为了开发某种特定功能,从Develop分支上面分出来的。开发完成后,要再并入Develop。功能分支的名字,可以采用feature-*的形式命名。
创建一个功能分支:

git checkout -b feature-x develop

开发完成后,将功能分支合并到develop分支:

git checkout develop
git merge --no-ff feature-x

删除feature分支:

git branch -d feature-x

四、预发布(release)分支
指发布正式版本之前(即合并到Master分支之前),我们可能需要有一个预发布的版本进行测试。预发布分支是从Develop分支上面分出来的,预发布结束以后,必须合并进Develop和Master分支。它的命名,可以采用release-*的形式。

创建一个预发布分支:

git checkout -b release-1.2 develop

确认没有问题后,合并到master分支:

git checkout master
git merge --no-ff release-1.2
# 对合并生成的新节点,做一个标签
git tag -a 1.2

再合并到develop分支:

git checkout develop
git merge --no-ff release-1.2

最后,删除预发布分支:

git branch -d release-1.2

五、修补bug(fixbug)分支
软件正式发布以后,难免会出现bug。这时就需要创建一个分支,进行bug修补。修补bug分支是从Master分支上面分出来的。修补结束以后,再合并进Master和Develop分支。它的命名,可以采用fixbug-*的形式。

创建一个修补bug分支:

git checkout -b fixbug-0.1 master

修补结束后,合并到master分支:

git checkout master
git merge --no-ff fixbug-0.1
git tag -a 0.1.1

再合并到develop分支:

git checkout develop
git merge --no-ff fixbug-0.1

最后,删除”修补bug分支”:

git branch -d fixbug-0.1

博客文章分类调整

最近发现博客的分类太多了,以至于快和文章的标签是一样多了。比如“计算机”大分类下面分java、javascript、HTML、CSS、Spring、Hibernate、oracle、windows、architecture、management等等,写一篇博客开始不知道要放到哪一个分类之下。

详细的分类和文章标签是有冲突的,文章标签本身也是分类,其应该反映文章内容的关键,可从文章标签大致可以了解文章再讲一些什么。这样一来文章分类目录就不应该反映文章内容的东西,而应该是一个更上层更抽象的分类,而且不应该有太多的类型。分析了一下过去文章的内容,提取出这几个分类:“技术知识”、“经验技巧”、“感悟”、“管理”、“收藏”,并把他们作为目录菜单。

通过分类调整,博客显得简洁了许多,条目更清晰明了了!

计算机存储计量单位KB/MB/GB/TB/PB/EB/ZB/YB/BB/NB/DB

数量级:
——————–
K = Kilo(千)
M = Mega(兆)
G = Giga(吉,千兆)
T = Tera(太)
P = Peta(拍)
E = Exa(艾)
Z = Zetta(泽它,皆)
Y = Yotta(尧)
B = Bronto
N = Nona
D = Dogga

计量单位:
——————–
b = Bit(位,比特) 计算机存储最小单位
B = Byte(字节) 它是计算机存储的基本单位. 1字节=8位,1个英文字符是1个字节(1B),1个GBK编码的汉字为2个字节(2B)。
Kb = KiloBit(千位,千比特)
KB = KiloByte(千字节)
Mb = MegaBit(兆位,兆比特)
MB = MegaByte(兆字节)
GB = GigaByte(吉字节,千兆字节)
TB = TeraByte(太字节)
PB = PetaByte(拍字节)
EB = ExaByte(艾字节)
ZB = ZettaByte(泽它字节,皆字节)
YB = YottaByte(尧字节)
BB = BrontoByte
NB = NonaByte
DB = DoggaByte

单位换算:
——————–
KB = 2^10 Bytes = 1,024 Bytes
MB = 2^20 Bytes = 1,048,576 Bytes
GB = 2^30 Bytes = 1,073,741,824 Bytes
TB = 2^40 Bytes = 1,099,511,627,776 Bytes
PB = 2^50 Bytes = 1,125,899,906,842,624 Bytes
EB = 2^60 Bytes = 1,152,921,504,606,846,976 Bytes
ZB = 2^70 Bytes = 1,180,591,620,717,411,303,424 Bytes
YB = 2^80 Bytes = 1,208,925,819,614,629,174,706,176 Bytes
BB = 2^90 Bytes = 1,237,940,039,285,380,274,899,124,224 Bytes
NB = 2^100 Bytes = 1,267,650,600,228,229,401,496,703,205,376 Bytes
DB = 2^110 Bytes = 1,298,074,214,633,706,907,132,624,082,305,024 Bytes

Keep a simple dream and follow it with no doubt.

岁月如梭,人事易变!生活总会遇到无法预知的问题,面对不同的压力!结婚生子、买房还贷、工作升职等等,每个人都会经历!再多的困难都无法阻挡,披荆斩棘,努力前行,追寻明天光明的太阳!

想起多年前开始使用QQ空间的时候,设置了一个副标题,在此贴出来继续勉励自己:

Keep a simple dream and follow it with no doubt.

记一次ClassNotFound的问题

同事说,在台北部署一个项目时遇到一个ClassNotFound的问题,而开发环境就不会发生,问我可能的原因,我想可能是环境classpath没有包含jar或者有class重复之类的问题。 他检查了一下,除了开发环境是简体系统,部署环境是繁体系统之外,所有配置设定都一样。当时想java的项目,跟简体繁体应该没关系吧,应该还是其他地方的问题,但因为自己有事情忙没有帮他看这个问题。

第二天他告诉我找到原因了:ClassNotFound的问题是那个类初始化的时候会加载国际化内容,而项目中有配置简体国际化,但繁体的国际化没配置,导致读取国际化失败,类加载失败。添加了繁体国际化就解决了!

不管程序设计上是否有问题,单从找问题的思路上,我也犯了错误。因为一般情况遇到ClassNotFound的问题都是classpath的问题,在此遇到这样的问题,习惯性的认为就是这样的原因造成。没有更进一步思考发生错误可能的原因还有其他情况,比如类加载失败等; 另外是当得知只存在简体繁体OS之差的情况,没有从这个关键点去思考,没有去想程序逻辑是否跟系统的语言版本有关系。 看来以后遇到问题的时候,还要对问题进行深入的了解,了解问题本质以及尽可能多的原因。另外程序运行会存在依赖关系,在问题模拟时,存在任何差异都应该要引起注意,多思考一下这样的差异是否和程序逻辑有关系。

说到找问题,程序员往往都会犯一个错误:对自己写的程序盲目自信!觉得自己写的代码绝无BUG,出了问题,简单检查一下程序说没问题,就开始怀疑是不是framework有问题?更有甚者会怀疑JDK有bug,OS有bug。 当然也不是framework、JDK、OS就不可能有问题,要明白framework、JDK、OS都是经过长时间的验证,且大家都在使用,其他人都没有遇到问题,让你发现问题的几率还是很小的。项目实践证明,绝大多数问题都是程序逻辑的问题,framework的问题很难遇到,JDK、OS的问题几乎是没有!

换灯记

租房的地方比较旧的安置房小区,房东安装的电灯都是挂丝的,之前已经换过多次节能灯,用不了多久就烧了!这次两个房间都烧了,去五金店买已经买不到挂丝的节能灯了,老板说现在都不用挂丝了,挂丝太危险,金属暴露在外,用摧丝的都包在塑料壳内,更安全!好吧!于是我买了两个节能灯和两个节能灯头!

今天一早,架起桌子凳子忙活起来!准备好螺丝刀、钳子、刀子!爬到桌子上的凳子上,把天花板上的挂丝头拆掉,但原来留下的线很短,很难操作!必须另外找铜线延长。屋里找了半天没找到,后来想起凉衣服的线是电线,于是从上面取下一节,扒去塑料皮,再截断成10厘米一小段。用钳子把这段铜线和原来天花板露出的一点线拧起来转几圈,将起伸到摧丝塑料壳内,然后穿进扣控中,再用螺丝刀把扣控螺丝旋紧,最后塑料壳旋紧,这样摧丝口就换好了! 节能灯旋上接口即可,相当简单!

一切顺利完成,但这个过程还是挺难的,要一直举着手做事情,而且脚还不能动,弄出一身汗水! 不过打开电闸,打开开关,电灯亮起的那一刻还是相当有成就感!