在bash脚本中如何从允许软件运行怎么设置脚本的node1切换到node2,并脚本中'切换命令'后的命令在node2上执行?

Linux Shell内建命令是有Bash自身提供的命令,不是文件系统的某个可执行文件。
[wudy@node2 test]$ which cd/usr/bin/which: no cd in .... # cd 不是可执行文件[wudy@node2 test]$ which more /bin/more# more是可执行文件,文件位置/bin/more
1.type__判断命令类型
[wudy@node2 test]$ type cd cd is a Shell builtin[wudy@node2 test]$ type moremore is /bin/more
2.’.’(点号)__执行程序
用于执行脚本(无论有没有执行权限)。如果没有运行权限,直接用”./scrpt”会报错。功能同source,读取命令并在当前环境下执行脚本,返回脚本最后一个命令的返回状态。若没有返回值则返回0,未找到脚本则返回false。
展开剩余91%
[wudy@node2 test]$ lltotal 4-rw-r--r-- 1 wudy labmember 78 Aug 9 13:59 HekkoWorld.sh# 不具有运行权限[wudy@node2 test]$ ./HekkoWorld.sh-bash: ./HekkoWorld.sh: Permission denied# ./执行报错权限[wudy@node2 test]$ . ./HekkoWorld.sh Hello WorldThis is a #不报错[wudy@node2 test]$ chmod 775 HekkoWorld.sh [wudy@node2 test]$ lltotal 4-rwxrwxr-x 1 wudy labmember 78 Aug 9 13:59 HekkoWorld.sh# 修改脚本权限[wudy@node2 test]$ ./HekkoWorld.sh Hello WorldThis is a # ./不报错[wudy@node2 test]$ source HekkoWorld.sh Hello WorldThis is a
(可左右滑动)
3.alias创建命令别名,unalias删除别名
对于比较常用和比较长的命令,创建别名,比如命令ll=’ls -l —color=tty‘
[wudy@node2 test]$ alias # 当前用户使用了别名的命令alias l.='ls -d .* --color=auto'alias ll='ls -l --color=auto'alias ls='ls --color=auto'alias mc='. /usr/libexec/mc/mc-wrapper.sh'alias qresume='qsig -s resume'alias qsuspend='qsig -s suspend'alias vi='vim'alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'[wudy@node2 test]$ alias myEchoHello='echo 'HelloWorld'' #在当前环境下定义命令别名[wudy@node2 test]$ myEchoHello #在当前环境下运行执行命令,只在当前环境下有效,重新登录后别名消失,永久保存需要将信息写入./bashrc中HelloWorld[wudy@node2 test]$ unalias myEchoHello #删除别名[wudy@node2 test]$ myEchoHello # 找不到已删除命令-bash: myEchoHello: command not found
(可左右滑动)
4. bgfg_jobs任务前后台切换
对于比较耗时的任务,通常放后台执行。
[wudy@node2 test]$ sh HelloWorld.sh#开始执行,但耗时长,放在前台一直占用终端无法执行其他任务,Ctrl+Z停止[1]+ stopped sh HelloWorld.sh [wudy@node2 test]$ jobs #查看当前任务[1]+ stopped sh HelloWorld.sh #任务暂停[wudy@node2 test]$ bg 1 or bg %1 #将[1]放到后台运行[1]+ sh HelloWorld.sh &[wudy@node2 test]$ fg 1 or fg %1 #将[1]放到前台运行[1]+ sh HelloWorld.sh [wudy@node2 test]$ sh HelloWorld.sh & #一开始就放到后台[1]+ sh HelloWorld.sh &[wudy@node2 test]$ nohup sh HelloWorld.sh & #一开始就放到后台,并将执行过程中输出信息输入到nohup文件中
(可左右滑动)
5. cd_改变当前目录
[wudy@node2 test]$ pwd #当前路径/public/home/wudy/test[wudy@node2 test]$ cd ../ #上一级路径[wudy@node2 ~]$ cd test/[wudy@node2 test]$ cd ~ #根目录[wudy@node2 ~]$ cd test/[wudy@node2 test]$ cd #根目录[wudy@node2 ~]$ cd ./ #./当前路径[wudy@node2 ~]$
6. declare_typeset声明变量
Shell脚本对变量声明要求不高,弱化了变量的类概念。declare可以声明变量类型。
[wudy@node2 test]$ num_1=23 #不指定类型直接定义变量(int)[wudy@node2 test]$ echo $num_1 #使用变量前加$23[wudy@node2 test]$ num_2=3.144 #浮点数[wudy@node2 test]$ echo $num_23.144[wudy@node2 test]$ char_1=abc # str字符串[wudy@node2 test]$ echo $char_1abc[wudy@node2 test]$ declare -i num_3=211 #declare -i声明变量为int类型[wudy@node2 test]$ echo $num_3211[wudy@node2 test]$ unset num_3[wudy@node2 test]$ echo $num_3 #空值[wudy@node2 test]$ declare -r num_4=344 #declare -r声明变量只读,不可修改[wudy@node2 test]$ echo $num_4344[wudy@node2 test]$ num_4=123-bash: num_4: readonly variable #修改失败[wudy@node2 test]$ unset num_4-bash: unset: num_4: cannot unset: readonly variable #unset删除变量赋值失败[wudy@node2 test]$ declare -a arr_1='([0]=23 [1]=34 [2]=45)' #declare -a 声明变量为数组('([0]=X [1]=X [2]=X……)')[wudy@node2 test]$ echo ${arr[2]} #使用没有定义的变量不会报错,只会输出值为空 #输出值为空[wudy@node2 test]$ echo ${arr_1[2]} # {数字变量名[number]}45[wudy@node2 test]$ declare -x pat_1=/bin/bash # declare -x 声明变量为环境变量[wudy@node2 test]$ echo $pat_1/bin/bash[wudy@node2 test]$ cat fun.sh # 函数#! /bin/bashfunc_1(){ echo 'Fun_1'}func_2(){ echo 'Fun_2'}echo 'declare -F :'declare -Fechoecho 'declare -f :'declare -f[wudy@node2 test]$ sh fun.sh # declare -F显示脚本中定义的函数,-f显示脚本中定义的函数体declare -F :declare -f func_1declare -f func_2declare -fx moduledeclare -f :func_1 () { echo 'Fun_1'}func_2 () { echo 'Fun_2'}module () { eval `/usr/bin/modulecmd bash $*`}declare -fx module
(可左右滑动)
7. echo_打印
默认最后每一行后加上换行符,使用-n参数可以不换行;若要打印转义字符,需要加参数-e。
[wudy@node2 test]$ echo 'Hello World'Hello World[wudy@node2 test]$ echo -n 'Hello World' #echo -n 结尾无换行符Hello World[wudy@node2 test]$ echo 'n'n[wudy@node2 test]$ echo -e 'n' #打印换行符n#两行空格,第一行是n转义字符,第二行是默认换行符[wudy@node2 test]$ echo -en 'n'#不含默认的换行符[wudy@node2 test]$
8. break__从循环中跳出
-n表示跳出几层循环,n&当前循环次数则跳出所有循环。
[wudy@node2 test]$ cat break_1.sh #! /bin/bash# break examplefor I in A B C D Edo echo -n "$I:" for J in $(seq 1 10) do if [ $J -eq 5 ]; then break #在当前循环中跳出 #break 2 fi echo -n " $J" done echodoneecho[wudy@node2 test]$ sh break_1.sh A: 1 2 3 4B: 1 2 3 4C: 1 2 3 4D: 1 2 3 4E: 1 2 3 4[wudy@node2 test]$ cat break_1.sh #! /bin/bash# break examplefor I in A B C D Edo echo -n "$I:" for J in $(seq 1 10) do if [ $J -eq 5 ]; then #break break 2 #跳出2层循环 fi echo -n " $J" done echodoneecho[wudy@node2 test]$ sh break_1.sh A: 1 2 3 4
(可左右滑动)
《Linux系统命令及Shell脚本实践指南》,王军,机械工业出版社
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。Microsoft - Official Home Page
Microsoft - Official Home Page
可携带的强大功能
随心所欲,百变菁英
独具匠心,彰显自我。
真4K 60帧超高清游戏机。
通过新一代电脑亲身体验 Windows 的非凡魅力。
无论联机或脱机,均可随时随地访问你的文件。
下载适用于 IT 专业人士的 90 天免费评估版。
预定开发版。改变你的世界。
脱离服务器的束缚 - 无需管理基础结构即可更快地构建应用。
了解更多微软中国市场活动
看资深大咖分享中小企业 IT 管理心得,并演示 O365 管理工作实践
关注 Microsoft用javascript实现页内搜索的脚本代码
function encode(s){
return s.replace(/&/g,"&").replace(//g,"&").replace(/([\\\.\*\[\]\(\)\$\^])/g,"\\$1");
function decode(s){
return s.replace(/\\([\\\.\*\[\]\(\)\$\^])/g,"$1").replace(/&/g,"&").replace(/&/g,"([^]*)/gi,"$1");
obj.innerHTML=t;
var cnt=loopSearch(s,obj);
t=obj.innerHTML
var r=/{searchHL}(({(?!\/searchHL})|[^{])*){\/searchHL}/g
t=t.replace(r,"$1");
obj.innerHTML=t;
alert("搜索到关键词"+cnt+"处")
function loopSearch(s,obj){
var cnt=0;
if (obj.nodeType==3){
cnt=replace(s,obj);
for (var i=0,c;c=obj.childNodes[i];i++){
if (!c.className||c.className!="highlight")
cnt+=loopSearch(s,c);
function replace(s,dest){
var r=new RegExp(s,"g");
var t=dest.nodeV
var cnt=0;
if (tm=t.match(r)){
t=t.replace(r,"{searchHL}"+decode(s)+"{/searchHL}")
dest.nodeValue=t;
.highlight{background:font-weight:color:}
"多次以捐赠的名义向我国转移不合格医疗器械,甚至医疗垃圾。"国家质检总局一纸"封杀令"使得AGAPE、LDS等美国基金会出现在中国公众视线里。
  虽然基金会代表宣称并不知情,但"医疗垃圾"以捐赠的形式先后出现在湖北、北京、安徽、内蒙古等地。
  医疗垃圾在欧美国家的处理费用高昂是一个事实,而记者了解到,AGAPE输入中国的3万美元"捐赠物资",空运费用高达40万美元。
  "我们正联合海关总署、商务部、民政部规范国外捐赠机构的捐赠行为,并将对相关违反我国法律法规的国外捐赠机构严肃处理。"
  在昨天下午召开的新闻发布会上,国家质检总局检验监督司司长王新做出上述表态。此前的11月4日,该局的一纸公告成了"美国问题捐赠"事件的放大镜与封杀令。
  这份标号为"2005年第159号"的公告称,鉴于美国AGAPE基金会"多次以捐赠的名义向我国转移不合格医疗器械,甚至医疗垃圾",自公告发布之日起停止其向中国出口医疗器械。
  就在11月4日当天,来自美国LDS基金会的一批捐赠物,分三个集装箱自天津港(行情 - 留言)入关,随后经中华慈善总会调拨分配给北京、安徽等地。
  截至11月11日,综合海关与质检部门的通报,湖北、安徽、北京、内蒙古以及湖南五省市,均出现过来自美国的"问题捐赠"。
  11月中旬,国家质检总局已向美国驻华大使馆通报了上述情况,后者同意依法就此展开调查。
  在昨天的新闻发布会上,央视《每周质量报告》记者称,该栏目组在湖南、湖北一些医院拍到了"问题捐赠"堆积在医院的画面。王新表示,他们只能保证今年查处的这两大批"问题捐赠"未流入民间。
  在依法严肃查处国外捐赠机构的同时,质检、民政部门将联手加强国内受赠民间机构的管理。"我们希望,能借这次机会填补海外捐赠法律方面的空白。"会后,王新在接受《新京报》记者采访时说。
  祸起武汉
  9月6日,亚心医院,湖北检验检疫局对两批先后空运抵此的捐赠物资例行检验。
  到现场的10余名成员中,除质检工作人员,还有来自美国AGAPE基金会、武汉市慈善协会和武汉亚心医院三方的代表。
  这两批医疗用品由美国AGAPE基金会捐赠给武汉市慈善协会,价值29422美元,共138647件、548箱,主要为心脏手术包、注射器、试剂、轮椅等。根据捐赠双方于日和6月13日签署的两份文件,两批物资均对口提供给亚心医院。
  现场的检验结果出人意料。据湖北电视台拍摄的画面,轮椅多数不完整,部分药品至2004年11月即已到期。
  国家质检总局通报的结果是:捐赠医疗器械第一批到货161纸箱,大部分产品已经于2005年6月(到货日)前过期;第二批共387个纸箱,绝大部分产品失效期在1990年到2004年之间,并有大量一次性注射器裸放在箱内,试剂和不明液体外流,致使大部分产品霉变、污染,轮椅、试验箱和部分一次性用品为二手废旧用品。
  湖北检验检疫局当场对货物实施隔离封存,另抽取样品送至武汉某医科大学做进一步鉴定。后者得到的结果是:样品有一部分为已使用和被严重污染的医疗用品,如再使用后患无穷。如实施销毁同样会造成环境污染。
  "看到这些医疗用品,我们当场就拒收了。"武汉市慈善总会一位人士介绍,根据捐赠双方的合约,"美国A
GAPE基金会捐赠的医疗耗材,必须符合中国《商品检验法》,如检验不合格,造成的一切后果由(美国田纳西州)AGAPE基金会承担"。
  出现在检验现场的A GAPE基金会代表封卓奇,自称对此并不知情。
  10月中旬,同样在武汉,当地海关再曝一起"美国问题捐赠"。这起被视为迄今为止武汉海关查获的最大规模"洋医疗垃圾",重约10吨,价值36万余美元。由中华慈善总会分拨给湖北省慈善协会接收,提供者则为美国LDS基金会(LDSCharities)。
[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
&FORM name=search onsubmit=&return findInPage(this.string.value);&&
&INPUT onchange=&n = 0;& size=15 name=string value=&首相&&
&INPUT type=submit value=页内搜索...&&/FORM&
&SCRIPT language=JavaScrip
如何动态添加单元格!! 复制代码 代码如下: 用insertRow()和insertCell()方法 其用法如下: insertRow()
复制代码 代码如下: var newTR=TableOBJ.insertRow(N); 复制代码 代码如下: 其中N表示插入到第几行!
说明:当N=0时,插入到最上面一行!当N=-1时插入到最后一行,相当省略该参数!
insertCell() 复制代码 代码如下: var newTD=TrOBJ.insertCell(N); 其中N表示插入到第几列!
复制代码 代码如下: &script type=&text/vbscript&&
Function str2asc(strstr)
str2asc = hex(asc(strstr))
End Function
Function asc2str(ascasc)
asc2str = chr(ascasc)
End Function
&/script& 将vbscript函数转成javascrip
本文实例讲述了JavaScript组件焦点与页内锚点间传值的方法.分享给大家供大家参考.具体分析如下: 上述的这两个小功能在一些新式的手机页面是很有用的. 如何光标放上输入框就触发事件,离开输入框就触发另一个事件呢?即使用户不输入任何东西-- 页间传值很简单,但在页内的锚点之间是如何传值呢? 一.基本目标 有一个页面,上面有一个输入框,一个超级链接,这两个东西是没有任何关联的, 只是因为功能不大,所以把两个功能合起来写 1.输入框功能 一旦把光标放上对话框背景就变成红色,一旦用户的鼠标点击其他地
本文实例讲述了php站内搜索关键词变亮的实现方法.分享给大家供大家参考.具体分析如下: 我们这个做法是把搜索结果出来,与搜索关键词相同的替换成高亮的字, 我们会用到str_replace(你找的关键字,&带有高亮的html标签&你找的关键字,$str); 就这么容易了,好了下面我们来看一个实例吧. 先创建一个数据库:create database 'searchKey'; 再创建表,SQL建库代码如下: 复制代码 代码如下: CREATE TABLE `fangke_cc`.`search`
本文实例讲述了JavaScript实现body内任意节点的自定义属性功能.分享给大家供大家参考,具体如下: 在HTML中body内的任意节点是可以自定义属性的,当然不包括body, 比如以下的代码: &!DOCTYPE html PUBLIC &-//W3C//DTD XHTML 1.0 Transitional//EN& &http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&& &htm
对于一个网站来说,使用搜索引擎来进行站内搜索往往比自己编写的站内搜索更高效,并且不占用网站服务器的资源,下面是我搜集到的几个主要搜索引擎(Google和百度.雅虎)的站内搜索代码,使用时只需要将代码里的&www.jb51.net&替换成你的网址即可. &!--Google站内搜索开始--& &form method=get action=&http://www.google.com/search&& &input type=text n
首先,声明方法很多种,直接间接的方法都有,只罗列一般情况下的两种模式: 假设我们要装入的代码是a.js: var foo=function(){ document.write(&I am a.js content foo() function by never-online&); }; 一.直接插入src,这种方法简单而直接,但有局限性, 1) &script& var x=document.createElement(&SCRIPT&); x.src=
本文实例讲述了python实现搜索指定目录下文件及文件内搜索指定关键词的方法.分享给大家供大家参考.具体实现方法如下: #!/usr/bin/python -O # -*- coding: UTF-8 -*- &&& Sucht rekursiv in Dateiinhalten und listet die Fundstellen auf. &&& __author__ = &Jens Diemer& __license__沈冠雄的博客 | 产品设计/研发,追究品质生活
本文用于快速掌握Markdown语法,并用于备查。
为什么用Markdown
Markdown的优点
写作中添加简单符号即完成排版,所见即所得。让你专注于文字而不是排版。
格式转换方便,Markdown 的文本你可以轻松转换为 html、pdf等。
可以保存称纯文本
Markdown简要规则
用1~6位递增的’#’,定义一段文字为标题
# 标题一 H1
## 标题二 H2
### 标题三 H3
#### 标题四 H4
##### 标题五 H5
###### 标题六 H6
用‘*’ ‘+’或‘-’,定义一段文字为无序列表
用‘1. ’‘2. ’…‘n. ’,定义一段文字为有序列表
用3位以上的‘*’ ‘+’或‘-’,定义一行分割线
未完待续。。。
本条目发布于。属于分类。作者是。
Mac下office 2016可以通过自签名的方法完成“激活”。但是如果用过其它的“激活”方法的话,会损坏文件的完整性,office 2016会频繁崩溃闪退。
重新安装office 2016,覆盖原安装文件;重新自签名“激活”。
1. 微软官网下载office.1 更新包
地址:https://support.microsoft.com/zh-cn/kb/3082420
2. 分别安装Word、Excel、PowerPoint、Outlook
3. 安装自签名的方法重新“激活”
解决完成!现在可以畅快地享受office 2016了。
本条目发布于。属于分类。作者是。
移动素材库
工欲善其事必先利其器,素材库则是我们必不可少的利器。Axure RP本身源自Web设计,针对移动应用设计的支持并不完美。所以合理使用第三方开发的素材库(Widget Library),可以节省我们重新绘制APP基础部件的时间,提高产品设计的专注度及效率。 以下是收集整理的一些第三方付费素材库:
UXDesign.today
费用:5 USD(折合人民币32元)
AXLibrary.com
费用:87 USD(折合人民币556.8元)
AXEmplate.com
费用:38 USD(折合人民币243.2元)
移动APP设计尺寸
看到一张空白画布,我们就开始考虑APP的尺寸应该是多少?以下以几款主流iPhone为例,可以根据个人兴趣选择机型对应的Points列作为设计稿尺寸:
为什么不是Android?没有其他原因,就是不喜欢。这里可以写一篇《为什么喜欢iOS而不是Android》
Asset Resolution
Portrait (px)
1080 x 1920
750 x 1334
iPhone 55, 5S, 5C
640 x 1136
建议:以iPhone 6为标准 ,尺寸为375 x 667。演示时仅需要根据不同机型可调整Initial scale:
iPhone 5s:Initial scale 0.583
iPhone 6:Initial scale 1.0
iPhone 6 Plus:Initial scale 1.104
小技巧:按住Ctrl从标尺处拖拽全局参考线至横轴375、纵轴667,即可确定单页设计区域
APP设计规范
现在主流两大手机系统:iOS和Android,官方都对APP设计的指导文档:
iOS Human Interface Guidelines
官方地址:
Layout传送门:
Android Material Design
官方地址:中译版:Layout传送门:
以iPhone 6为,以下是一些常用的layout规范:
Status Bar(状态栏) 宽100%、高20pt
Navigation Bar(导航栏 )Toolbar(工具栏)宽100%、高44pt
Tab Bar(标签栏)宽100%、高49pt
Search Bar(搜索栏)宽100%、高43pt
PC上演示APP原型
写到此处,肚子微饿
创建一个Page叫做“iPhone Frame for Desktop View”,排序置顶
从第三方部件库中拖拽一个iPhone 6 的Body到当前Page
从default部件库拖拽Inline Frame到Body中心,设置weight:375 height:667,并调整位置至Body的屏幕位置
选中Inline Frame编辑Widget Properties的Frame Target属性为APP入口页,Frame Scrollbars为Never Show
在浏览器中预览当前页即可,APP会显示在iPhone 6 的body中
移动设备上演示APP原型
首先设置Preview Options里的Mobile/Device,勾选Include Viewport Tag,以便适配移动设备。再根据不同的iPhone 设备设置Initial Scale,这样即可在不同的设备上都完美适配。 Axure在移动设备上演示提供了两种方式:
导出Html文件,通过手机浏览器本地或远程查看
发布至Axure Share,通过下载AxShare应用或URL链接链接查看
建议:共享至Axure Share,手机通过AxShare应用查看。AxShare可以在线查看Cloud项目,也可以缓存到Local本地,同时满足实时预览及离线演示的需求。
如果基于公司信息安全的考虑,还是选择导出Html内网或下载至手机本地查看
参考资料:
The iOS Design Guidelines
本条目发布于。属于分类。作者是。
关注Docker这项技术差不多一年多了,最近关于Docker的使用案例越来越多,于是就想动手实验下这项技术。自己整理了一个入门手册,分享给大家。
Docker是什么
Docker是一种容器技术,它可以将应用和环境等进行打包,形成一个独立的,类似于iOS的APP形式的“应用”,这个应用可以直接被分发到任意一个支持Docker的环境中,通过简单的命令即可启动运行。Docker是一种最流行的容器化实现方案。和虚拟化技术类似,它极大的方便了应用服务的部署;又与虚拟化技术不同,它以一种更轻量的方式实现了应用服务的打包。使用Docker可以让每个应用彼此相互隔离,在同一台机器上同时运行多个应用,不过他们彼此之间共享同一个操作系统。Docker的优势在于,它可以在更细的粒度上进行资源的管理,也比虚拟化技术更加节约资源。
虚拟化和Docker架构对比,来自Docker官网
开始试验Docker之前,我们先来了解一下Docker的几个基本概念:
镜像:我们可以理解为一个预配置的系统光盘,这个光盘插入电脑后就可以启动一个操作系统。当然由于是光盘,所以你无法修改它或者保存数据,每次重启都是一个原样全新的系统。Docker里面镜像基本上和这个差不多。
容器:同样一个镜像,我们可以同时启动运行多个,运行期间的产生的这个实例就是容器。把容器内的操作和启动它的镜像进行合并,就可以产生一个新的镜像。
Docker基于技术实现,依赖于Linux内核,所以Docker目前只能在Linux以原生方式运行。目前主要的Linux发行版在他们的软件仓库中内置了Docker:
Ubuntu Trusty 14.04 (LTS)
Ubuntu Precise 12.04 (LTS)
Ubuntu Saucy 13.10
Docker要求64位环境,这些操作系统下可以直接通过命令安装Docker,老一些操作系统Docker官方也提供了安装方案。下面的实验基于CentOS 7进行。关于其他版本操作系统上Docker的安装,请参考官方文档:
在CentOS 7上安装Docker
使用yum从软件仓库安装Docker:
yum install docker
首先启动Docker的守护进程:
service docker start
如果想要Docker在系统启动时运行,执行:
chkconfig docker on
Docker在CentOS上好像和防火墙有冲突,应用防火墙规则后可能导致Docker无法联网,重启Docker可以解决。
Docker仓库
Docker使用类似git的方式管理镜像。通过基本的镜像可以定制创建出来不同种应用的Docker镜像。是Docker官方提供的镜像中心。在这里可以很方便地找到各类应用、环境的镜像。
由于Docker使用联合文件系统,所以镜像就像是夹心饼干一样一层层构成,相同底层的镜像可以共享。所以Docker还是相当节约磁盘空间的。要使用一个镜像,需要先从远程的镜像注册中心拉取,这点非常类似git。
docker pull ubuntu
我们很容易就能从Docker Hub镜像注册中心下载一个最新版本的ubuntu镜像到本地。国内网络可能会稍慢,提供了Docker Hub的国内加速服务,可以尝试配置使用。
运行一个容器
使用Docker最关键的一步就是从镜像创建容器。有两种方式可以创建一个容器:使用docker create命令创建容器,或者使用docker run命令运行一个新容器。两个命令并没有太大差别,只是前者创建后并不会立即启动容器。
以ubuntu为例,我们启动一个新容器,并将ubuntu的Shell作为入口:
docker run –it ubuntu:latest sh –c ‘/bin/bash’
这时候我们成功创建了一个Ubuntu的容器,并将当前终端连接为这个Ubuntu的bash shell。这时候就可以愉快地使用Ubuntu的相关命令了~可以快速体验一下。
参数-i表示这是一个交互容器,会把当前标准输入重定向到容器的标准输入中,而不是终止程序运行。-t指为这个容器分配一个终端。
好了,按Ctrl+D可以退出这个容器了。
在容器运行期间,我们可以通过docker ps命令看到所有当前正在运行的容器。添加-a参数可以看到所有创建的容器:
docker ps –a
[root@localhost ~]# docker ps -a
CONTAINER ID&&&&&&&&IMAGE&&&&&&&&&&&&&&&&&&&&&&&&COMMAND&&&&&&&&&&&&&&&&CREATED&&&&&&&&&&&& STATUS&&&&&&&&&&&&&&&&&&&&&&PORTS&&&&&&&&&&&&&& NAMES
cb2b06c83a50&&&&&&&&ubuntu:latest&&&&&&&&&&&&&&&&“sh -c /bin/bash”&&&&&&7 minutes ago&&&&&& Exited (0) 7 seconds ago&&&&&&&&&&&&&&&&&&&&&&&&trusting_morse
每个容器都有一个唯一的ID标识,通过ID可以对这个容器进行管理和操作。在创建容器时,我们可以通过–name参数指定一个容器名称,如果没有指定系统将会分配一个,就像这里的“trusting_morse”(什么鬼。。)。
当我们按Ctrl+D退出容器时,命令执行完了,所以容器也就退出了。要重新启动这个容器,可以使用docker start命令:
docker start –i trusting_morse
同样,-i参数表示需要交互式支持。
注意:每次执行docker run命令都会创建新的容器,建议一次创建后,使用docker start/stop来启动和停用容器。
在Docker容器运行期间,对文件系统的所有修改都会以增量的方式反映在容器使用的联合文件系统中,并不是真正的对只读层数据信息修改。每次运行容器对它的修改,都可以理解成对夹心饼干又添加了一层奶油。这层奶油仅供当前容器使用。当删除Docker容器,或通过该镜像重新启动时,之前的更改将会丢失。这样做并不便于我们持久化和共享数据。Docker的数据卷这个东西可以帮到我们。
在创建容器时,通过-v参数可以指定将容器内的某个目录作为数据卷加载:
docker run –it –v /home/www ubuntu:latest sh –c ‘/bin/bash’
在容器中会多一个/home/www挂载点,在这个挂载点存储数据会绕过联合文件系统。我们可以通过下面的命令来找到这个数据卷在主机上真正的存储位置:
docker inspect –f {{.Volumes}} trusting_morse
你会看到输出了一个指向到/var/lib/docker/vfs/dir/…的目录。cd进入后你会发现在容器中对/home/www的读写创建,都会反映到这儿。事实上,/home/www就是挂载自这个位置。
有时候,我们需要将本地的文件目录挂载到容器内的位置,同样是使用数据卷这一个特性,-v参数格式为:
docker run –it –v [host_dir]:[container_dir]
host_dir是主机的目录,container_dir是容器的目录。
容器和容器之间是可以共享数据卷的,我们可以单独创建一些容器,存放如数据库持久化存储、配置文件一类的东西,然而这些容器并不需要运行。
docker run —name dbdata ubuntu echo “Data container.”
在需要使用这个数据容器的容器创建时–volumes-from [容器名]的方式来使用这个数据共享容器。
Docker容器内的系统工作起来就像是一个虚拟机,容器内开放的端口并不会真正开放在主机上。可以使我们的容器更加安全,而且不会产生容器间端口的争用。想要将Docker容器的端口开放到主机上,可以使用类似端口映射的方式。
在Docker容器创建时,通过指定-p参数可以暴露容器的端口在主机上:
docker run –it –p 22 ubuntu sh –c ‘/bin/bash’
现在我们就将容器的22端口开放在了主机上,注意主机上对应端口是自动分配的。如果想要指定某个端口,可以通过-p [主机端口]:[容器端口]参数指定。
容器和容器之间想要网络通讯,可以直接使用–link参数将两个容器连接起来。例如WordPress容器对some-mysql的连接:
docker run —name some–wordpress —link some–mysql:mysql –p 8080:80 –d wordpress
通过Docker打包的应用,对外就像是一个密闭的exe可执行文件。有时候我们希望Docker能够使用一些外部的参数来使用容器,这时候参数可以通过环境变量传递进去,通常情况下用来传递比如MySQL数据库连接这种的东西。环境变量通过-e参数向容器传递:
docker run —name some–wordpress –e WORDPRESS_DB_HOST=10.1.2.3:3306 \
&&&&–e WORDPRESS_DB_USER=... –e WORDPRESS_DB_PASSWORD=... –d wordpress
关于Docker到现在就有了一个基本的认识了。接下来我会给大家介绍如何创建镜像,以及如何利用公有云直接发布的基于Docker的应用。
Docker强大的威力在于可以把自己开发的应用随同各种依赖环境一起打包、分发、运行。要创建一个新的Docker镜像,通常基于一个已有的Docker镜像来创建。Docker提供了两种方式来创建镜像:把容器创建为一个新的镜像、使用Dockerfile创建镜像。
将容器创建为镜像
为了创建一个新的镜像,我们先创建一个新的容器作为基底:
docker run –it ubuntu:latest sh –c ‘/bin/bash’
现在我们可以对这个容器进行修改了,例如我们可以配置PHP环境、将我们的项目代码部署在里面等:
apt–get install php
# some other opreations …
当执行完操作之后,我们按Ctrl+D退出容器,接下来使用docker ps -a来查找我们刚刚创建的容器ID:
docker ps –a
可以看到我们最后操作的那个ubuntu容器。这时候只需要使用docker commit即可把这个容器变为一个镜像了:
docker commit 8d ubuntu:myubuntu
这时候docker容器会被创建为一个新的Ubuntu镜像,版本名称为myubuntu。以后我们可以随时使用这个镜像来创建容器了,新的容器将自动包含上面对容器的操作。
如果我们要在另外一台机器上使用这个镜像,可以将一个镜像导出:
docker save –o myubuntu.tar.gz ubuntu:myubuntu
现在我们可以把刚才创建的镜像打包为一个文件分发和迁移了。要在一台机器上导入镜像,只需要:
docker import myubuntu.tar.gz
这样在新机器上就拥有了这个镜像。
注意:通过导入导出的方式分发镜像并不是Docker的最佳实践,因为我们有Docker Hub。
Docker Hub提供了类似GitHub的镜像存管服务。一个镜像发布到Docker Hub不仅可以供更多人使用,而且便于镜像的版本管理。关于Docker Hub的使用,之后我会单独写一篇文章展开介绍。另外,在一个企业内部可以通过自建的方式来统一管理和发布镜像。将Docker Registry集成到版本管理和上线发布的工作流之中,还有许多工作要做,在我整理出最佳实践后会第一时间分享。
使用Dockerfile创建镜像
使用命令行的方式创建Docker镜像通常难以自动化操作。在更多的时候,我们使用Dockerfile来创建Docker镜像。Dockerfile是一个纯文本文件,它记载了从一个镜像创建另一个新镜像的步骤。撰写好Dockerfile文件之后,我们就可以轻而易举的使用docker build命令来创建镜像了。
Dockerfile非常简单,仅有以下命令在Dockerfile中常被使用:
&image&[:&tag&]
从一个已有镜像创建,例如ubuntu:latest
MAINTAINER
Author &some-&
镜像作者名字,如Max Liu &some-&
&cmd&或者[‘cmd1’, ‘cmd2’…]
在镜像创建用的临时容器里执行单行命令
&src& &dest&
将本地的&src&添加到镜像容器中的&dest&位置
&path&或者[‘/var’, ‘home’]
将指定的路径挂载为数据卷
&port& [&port&…]
将指定的端口暴露给主机
&key& &value& 或者 &key& = &value&
指定环境变量值
[“executable”,”param1″,”param2″]
容器启动时默认执行的命令。注意一个Dockerfile中只有最后一个CMD生效。
ENTRYPOINT
[“executable”, “param1″, “param2″]
容器的进入点。
下面是一个Dockerfile的例子:
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith &ksmith@example.com&
RUN apt–get update && apt–get install –y ruby ruby–dev
RUN gem install sinatra
这里其他命令都比较好理解,唯独CMD和ENTRYPOINT我需要特殊说明一下。CMD命令可用指定Docker容器启动时默认的命令,例如我们上面例子提到的docker run -it ubuntu:latest sh -c ‘/bin/bash’。其中sh -c ‘/bin/bash’就是通过手工指定传入的CMD。如果我们不加这个参数,那么容器将会默认使用CMD指定的命令启动。ENTRYPOINT是什么呢?从字面看是进入点。没错,它就是进入点。ENTRYPOINT用来指定特定的可执行文件、Shell脚本,并把启动参数或CMD指定的默认值,当作附加参数传递给ENTRYPOINT。
不好理解是吧?我们举一个例子:
ENTRYPOINT [‘/usr/bin/mysql’]
CMD [‘-h 192.168.100.128’, ‘-p’]
假设这个镜像内已经准备好了mysql-client,那么通过这个镜像,不加任何额外参数启动容器,将会给我们一个mysql的控制台,默认连接到192.168.100.128这个主机。然而我们也可以通过指定参数,来连接别的主机。但是不管无论如何,我们都无法启动一个除了mysql客户端以外的程序。因为这个容器的ENTRYPOINT就限定了我们只能在mysql这个客户端内做事情。这下是不是明白了~
因此,我们在使用Dockerfile创建文件的时候,可以创建一个entrypoint.sh脚本,作为系统入口。在这个文件里面,我们可以进行一些基础性的自举操作,比如检查环境变量,根据需要初始化数据库等等。下面两个文件是我在SimpleOA项目中添加的Dockerfile和entrypoint.sh,仅供参考:
在准备好Dockerfile之后,我们就可以创建镜像了:
docker build –t starlight36/simpleoa .
关于Dockerfile的更详细说明,请参考
杂项和最佳实践
在产品构建的生命周期里使用Docker,最佳实践是把Docker集成到现有的构建发布流程里面。这个过程并不复杂,可以在持续集成系统构建测试完成后,将打包的步骤改为docker build,持续集成服务将会自动将构建相应的Docker镜像。打包完成后,可以由持续集成系统自动将镜像推送到Docker Registry中。生产服务器可以直接Pull最新版本的镜像,更新容器即可很快地实现更新上线。目前Atlassian Bamboo已经支持Docker的构建了。
由于Docker使用联合文件系统,所以并不用担心多次发布的版本会占用更多的磁盘资源,相同的镜像只存储一份。所以最佳实践是在不同层次上构建Docker镜像。比如应用服务器依赖于PHP+Nginx环境,那么可以把定制好的这个PHP环境作为一个镜像,应用服务器从这个镜像构建镜像。这样做的好处是,如果PHP环境要升级,更新了这个镜像后,重新构建应用镜像即可完成升级,而不需要每个应用项目分别升级PHP环境。
新手经常会有疑问的是关于Docker打包的粒度,比如MySQL要不要放在镜像中?最佳实践是根据应用的规模和可预见的扩展性来确定Docker打包的粒度。例如某小型项目管理系统使用LAMP环境,由于团队规模和使用人数并不会有太大的变化(可预计的团队规模范围是几人到几千人),数据库也不会承受无法承载的记录数(生命周期内可能一个表最多会有数十万条记录),并且客户最关心的是快速部署使用。那么这时候把MySQL作为依赖放在镜像里是一种不错的选择。当然如果你在为一个互联网产品打包,那最好就是把MySQL独立出来,因为MySQL很可能会单独做优化做集群等。
使用公有云构建发布运行Docker也是个不错的选择。国内提供了从构建到发布到运行的全生命周期服务。特别适合像微擎这种微信公众平台、或者中小型企业CRM系统。上线周期更短,比使用IAAS、PAAS的云服务更具有优势。
参考资料:
深入理解Docker Volume WordPress&
Docker学习—镜像导出
Dockerfile Reference 关于Dockerfile&
该文转自starlight36.com
本条目发布于。属于分类。作者是。
从 LAMP 到 MEAN
MEAN 不仅仅是一次首字母缩写的简单重新安排与技术升级。将基础平台从操作系统 (Linux) 转变为 JavaScript 运行时 (Node.js) 让操作系统变得独立:Node.js 在 Windows(R) 与 OS X 上的运行情况和在 Linux 上一样优秀。
Node.js 同样取代了 LAMP 堆栈中的 Apache。但 Node.js 远远不止是一种简单的 Web 服务器。事实上,用户不会将完成后的应用程序部署到单机的 Web 服务器上;相反,Web 服务器已经包含在应用程序中,并已在 MEAN 堆栈中自动安装。结果,部署过程得到了极大简化,因为所需的 Web 服务器版本已经与余下的运行时依赖关系一起得到了明确定义。
从传统数据库(如 MySQL)到 NoSQL,再到无架构的、以文档为导向的持久存储(如 MongoDB),这些代表着持久化策略发生了根本性的转变。用户花费在编写 SQL 上的时间将会减少,将会有更多的时间编写 JavaScript 中的映射/化简功能。用户还能省掉大量的转换逻辑,因为 MongoDB 可以在本地运行 。因此,编写
Web 服务变得前所未有的容易。
但从 LAMP 到 MEAN 的最大转变在于从传统的服务器端页面生成变为客户端 。借助 Express 仍然可以处理服务器端的路由与页面生成,但目前的重点在客户端视图上,而 AngularJS 可以实现这一点。这种变化并不仅仅是将
工件从服务器转移到客户端。用户还要尝试从习惯的同步方式转而使用基本由事件驱动的、实质上为异步的方式。或许最重要的一点是,您将从以页面为中心的应用程序视图转到面向组件的视图。
MEAN 堆栈并非以移动为中心,AngularJS 在桌面电脑、笔记本电脑、智能手机、平板电脑和甚至是智能电视上的运行效果都一样,但它不会把移动设备当作二等公民对待。而且测试事后不再是问题:借助世界级的测试框架,比如、 和 ,您可以为自己的 MEAN 应用程序编写深入而又全面的测试套件。
准备好获得 MEAN 了吗?
安装 Node.js
您需要安装 Node.js,以便在本系列中的示例应用程序上工作,如果尚未安装它,那就立刻开始安装吧。
如果使用 UNIX(R) 风格的操作系统(Linux、Mac OS X 等),我推荐使用 。(否则,在 上单击Install,下载适合您操作系统的安装程序,然后接受默认选项即可。)借助 NVM,您可以轻松下载 Node.js,并从命令行切换各种版本。这可以帮助您从一个版本的 Node.js 无缝转移到下一版本,就像我从一个客户项目转到下一个客户项目一样。
NVM 安装完毕后,请输入命令 nvm ls-remote 查看哪些 Node.js 版本可用于安装,如清单 1 中所示。
清单 1. 使用 NVM 列出可用的 Node.js 版本
$ nvm ls-remote
输入 nvm ls 命令可以显示本地已经安装的 Node.js 版本,以及目前正在使用中的版本。
在撰写本文之际,Node 网站推荐 v0.10.28 是最新的稳定版本。输入 nvm install v0.10.28 命令在本地安装它。
安装 Node.js 后(通过 NVM 或平台特定的安装程序均可),可以输入 node --version 命令来确认当前使用的版本:
$ node --version
什么是 Node.js?
Node.js 是一种 headless JavaScript 运行时。它与运行在 Google Chrome 内的 JavaScript 引擎(名叫 V8)是一样的,但使用 Node.js 可以从命令行(而非浏览器)运行 JavaScript。
我曾有些学生嘲笑过从命令行运行 JavaScript 的主意:“如果没有要控制的 HTML,那 JavaScript 还有什么好处呢?” JavaScript 是在浏览器(Netscape Navigator 2.0)中来到这个世界的,因此那些反对者的短视和天真是可以原谅的。
事实上,JavaScript 编程语言并未针对
操作或形成 Ajax 请求提供本地功能。该浏览器提供了 DOM API,可以方便用户使用 JavaScript 来完成这类工作,但在浏览器之外的地方,JavaScript 不具备这些功能。
下面给出了一个例子。在浏览器中打开一个 JavaScript 控制台(参见 )。输入 navigator.appName。获得响应后,请输入 navigator.appVersion。得到的结果类似于图 1 中所示。
图 1. 在 Web 浏览器中使用 JavaScript navigator 对象
在图 1 中,Netscape 是对 navigator.appName 的响应,而对 navigator.appVersion 的响应则是经验丰富的 Web 开发人员已经熟知但爱恨不一的、神秘的开发人员代理字符串。在图 1 中(截自 OS X 上的 Chrome 浏览器),该字符串是 5.0 (M Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0. Safari/537.36。
现在,我们要创建一个名为 test.js 的文件。在文件中输入同样的命令,并将每个命令包含在 console.log() 调用中:
console.log(navigator.appName);
console.log(navigator.appVersion);
保存文件并输入 node test.js 来运行它,如清单 2 中所示。
清单 2. 查看 Node.js 中的 navigator is not defined 错误
$ node test.js
/test.js:1
ion (exports, require, module, __filename, __dirname) { console.log(navigator.
ReferenceError: navigator is not defined
at Object.&anonymous& (/test.js:1:75)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
正如您看到的那样,navigator 在浏览器中可用,但在 Node.js 中不可用。(不好意思,让您的第一个 Node.js 脚本失败了,但我想确保让您相信,在浏览器中运行 JavaScript 与在 Node.js 中运行它是不同的。)
根据堆栈跟踪的情况,正确的 Module 没有得到加载。(Modules 是在浏览器中运行 JavaScript 与在 Node.js 中运行它之间的另一主要区别。我们将立刻讲述 Modules 的更多相关内容。)为了从 Node.js 获得类似的信息,请将 test.js 的内容修改为:
console.log(process.versions)
console.log(process.arch)
console.log(process.platform)
再次输入 node test.js,可以看到类似于清单 3 中的输出。
清单 3. 在 Node.js 中使用过程模块
$ node test.js
{ http_parser: '1.0',
node: '0.10.28',
v8: '3.14.5.9',
ares: '1.9.0-DEV',
uv: '0.10.27',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1g' }
在 Node.js 中成功运行第一个脚本之后,我们将接触下一个主要概念:模块。
什么是模块?
可以在 JavaScript 中创建单一功能的函数,但与在 Java、Ruby 或 Perl 中不同,无法将多个函数打包到一个能够导入导出的内聚模块或 ”包“ 中。当然,使用 &script& 元素可以包含任意 JavaScript 源代码文件,但这种历史悠久的方法在两个关键方面缺少正确的模块声明。
首先,使用 &script& 元素包含的任意 JavaScript 将被加载到全局命名空间中。使用模块可以导入的函数被封装在一个局部命名的变量中。其次,同时更为关键的是,可以使用模块显式地声明依赖关系,而使用 &script& 元素则做不到这一点。结果,导入 Module A 时也会同时导入依赖的 Modules B 和 C。当应用程序变得复杂时,传递依赖关系管理很快将成为一种关键需求。
模块是用户衷心期盼的下一 JavaScript 主要版本 (ECMAScript 6) 的功能,但直到该版本被广泛接受之前,Node.js 目前使用的是它自己基于
规范的模块版本。
使用 require 关键字可以在脚本中包含 CommonJS 模块。例如,清单 4 是对 Node.js 主页上的 Hello World 脚本稍微进行修改后的版本。创建一个名为 example.js 的文件,并将清单 4 中的代码复制到其中。
清单 4. Node.js 中的 Hello World
var http = require('http');
var port = 9090;
http.createServer(responseHandler).listen(port);
console.log('Server running at http://127.0.0.1:' + port + '/');
function responseHandler(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('&html&&body&&h1&Hello World&/h1&&/body&&/html&');
输入 node example.js 命令运行新的 Web 服务器,然后在 Web 浏览器中访问 。
看一看清单 4 中的头两行。您很可能写过几百次(或几千次)像 var port = 9090; 这样的简单语句。这条语句定义了一个名为 port 的变量,并将数字 9090 赋值给它。第一行 (var http = require('http');) 用于导入一个 CommonJS 模块。它引入 http 模块并将它指派给一个局部变量。 and assigns it to a local variable. All of the corresponding modules that http 依赖的所有对应模块也同时被 require 语句导入。
example.js 后面的代码行:
创建一个新的 HTTP 服务器。
指定一个函数来处理响应。
开始监听指定端口上进入的 HTTP 请求。
这样通过寥寥几行 JavaScript 代码,就可以在 Node.js 中创建了一个简单的 Web 服务器。在本系列随后的文章中您会看到,Express 将这个简单的例子被扩展用于处理更为复杂的路由,同时还将提供静态与动态生成的资源。
http 模块是 Node.js 安装的标准组件之一。其他标准的 Node.js 模块还支持文件 I/O,读取来自用户的命令行输入,处理底层的 TCP 和 UDP 请求等等。访问 Node.js 文档的
部分,查看标准模块的完整列表并了解它们的功能。
尽管模块列表内容十分丰富,但与可用的第三方模块列表相比,仍然是小巫见大巫。要访问它们,您需要熟悉另一个命令行实用工具:NPM。
什么是 NPM?
NPM 是 Node Packaged Modules 的简写。要查看包含超过 75,000 个公用第三方 Node 模块的清单,请访问 。在网站上搜索 yo 模块。图 2 显示了搜索结果。
图 2. yo 模块的详细情况
结果页面简要介绍了该模块(搭建 Yeoman 项目的 CLI 工具),并显示它在过去一天、一周和一月内被下载的次数、编写该模块的作者、它依赖于哪些其他的模块(如果存在)等内容。最重要的是,结果页面给出了安装该模块的命令行语法。
要从命令行获取关于 yo 模块的类似信息,请输入 npm info yo 命令。(如果您还不知道模块的官方名称,可以输入 npm search yo 来搜索名称中包含字符串 yo 的所有模块。)npm info 命令显示模块的 package.json 文件的内容。
了解 package.json
每个 Node.js 模块都必须关联一个格式良好的
文件,因此,熟悉此文件的内容是值得的。清单 5、清单 6 和清单 7 分三部分显示了 yo 模块的 package.json 文件的内容。
如清单 5 中所示,第一个元素通常是 name、description 和一个可用 versions 的 JSON 数组。
清单 5. package.json,第 1 部分
$ npm info yo
{ name: 'yo',
description: 'CLI tool for scaffolding out Yeoman projects',
'dist-tags': { latest: '1.1.2' },
'1.1.2' ],
要安装一个模块的最新版本,请输入 npm install package 命令。输入 npm install package@version 可以安装一个特定的版本。
如清单 6 中所示,接下来将显示作者、维护者和可以直接查找源文件的 GitHub 库。
清单 6. package.json,第 2 部分
author: 'Chrome Developer Relations',
repository:
{ type: 'git',
url: 'git://github.com/yeoman/yo' },
homepage: 'http://yeoman.io',
[ 'front-end',
'development',
'scaffold',
'stack' ],
在这个例子中,还可以看到一个指向项目主页的链接和一个相关关键字的 JSON 数组。并非所有 package.json 文件中都会出现所有这些字段,但用户很少会抱怨与一个项目相关的元数据太多。
最后,清单 7 中列出了附有显式版本号的依赖关系。这些版本号符合主版本.次版本.补丁版本的常用模式,被称为 (语义版本控制)。
清单 7. package.json,第 3 部分
engines: { node: '&=0.8.0', npm: '&=1.2.10' },
dependencies:
{ 'yeoman-generator': '~0.16.0',
nopt: '~2.1.1',
lodash: '~2.4.1',
'update-notifier': '~0.1.3',
insight: '~0.3.0',
'sudo-block': '~0.3.0',
async: '~0.2.9',
open: '0.0.4',
chalk: '~0.4.0',
findup: '~0.1.3',
shelljs: '~0.2.6' },
peerDependencies:
{ 'grunt-cli': '~0.1.7',
bower: '&=0.9.0' },
devDependencies:
{ grunt: '~0.4.2',
mockery: '~1.4.0',
'grunt-contrib-jshint': '~0.8.0',
'grunt-contrib-watch': '~0.5.3',
'grunt-mocha-test': '~0.8.1' },
这个 package.json 文件表明,它必须安装在 0.8.0 或更高版本的 Node.js 实例上。如果试图使用 npm install 命令安装一个不受支持的版本,那么安装将会失败。
除了平台要求之外,这个 package.json 文件还提供几个依赖关系列表:
dependencies 部分列出了运行时的依赖关系。
devDependencies 部分列出了开发过程中需要的模块。
部分支持作者定义项目之间的 ”对等“ 关系。这种功能通常用于指定基础项目与其插件之间的关系,但在这个例子中,它指出了包含 Yeoman 项目与 Yo 的其他两个项目(Grunt 与 Bower)。
如果在不指定模块名的情况下输入 npm install 命令,那么 npm 会访问当前目录中的 package.json 文件,并安装我刚刚讨论过的三部分内容中列出的所有依赖关系。
安装一个能正常工作的 MEAN 堆栈,下一步是安装 Yeoman 与相应的 Yeoman-MEAN 生成器。
安装 Yeoman
作为一名 Java 开发人员,我无法想象在没有诸如 Ant 或 Maven 这样的编译系统的情况下如何启动一个新项目。类似地,Groovy 和 Grails 开发人员依靠的是 Gant(Ant 的一种 Groovy 实现)或 Gradle。这些工具可以搭建起一个新的目录结构,动态下载依赖关系,并准备好将项目发布。
在纯粹的 Web 开发环境中,Yeoman 可以满足这种需要。Yeoman 是三种 Node.js 工具的集合,包括用于搭建的纯 JavaScript 工具 Yo,管理客户端依赖关系的 Bower,以及准备项目发布的 Grunt。通过分析
可以得出这样的结论:安装 Yo 时也会安装它对等的 Grunt 和 Bower,这要感谢 package.json 中的 peerDependencies 部分。
通常,输入 npm install yo --save 命令可以安装 yo 模块并更新 package.json 文件中的 dependencies 部分。(npm install yo --save-dev 用于更新 devDependencies 部分。)但这三个对等的 Yeoman 模块算不上是特定于项目的模块,它们是命令行实用工具,而非运行时依赖关系。要全局安装一个 NPM 包,需要在 install 命令后增加一个 -g 标志。
在系统上安装 Yeoman:
npm install -g yo
在完成包安装后,输入 yo --version 命令来验证它已经在运行中。
Yeoman 与基础架构的所有余下部分都准备就绪后,便可以开始安装 MEAN 堆栈了。
安装 MeanJS
您可以手动安装 MEAN 堆栈的每一部分,但需要十分小心。谢天谢地,Yeoman 通过其 generators(生成器) 提供了一种更轻松的安装方式。
Yeoman 生成器就是引导一个新 Web 项目更轻松的方式。该生成器提供了基础包及其所有依赖关系。此外,它通常还会包含一个工作的编译脚本及其所有相关插件。通常,该生成器还包含一个示例应用程序,包括测试在内。
Yeoman 团队构建和维护了几个 。(超过 800 个)远远超过官方生成器的数量。
您将用于引导第一个 MEAN 应用程序的社区生成器被称为 ,这也在意料之中。
在 MEAN.JS 主页上,单击 Yo Generator 菜单选项或者直接访问
页面,图 3 中显示了其中的一部分。
图 3. MEAN.JS Yeoman 生成器
该页面上的说明指出要首先 Yeoman,这一点您已经完成。
还需要安装bower和grunt-cli
npm install -g bower
npm install -g grunt-cli
下一步是全局安装 MEAN.JS 生成器:
npm install -g generator-meanjs
生成器准备就绪后,便可以开始创建您的第一个 MEAN 应用程序了。创建一个名为 test 的目录,使用 cd 命令进入它,然后输入 yo meanjs命令生成应用程序。回答最后两个问题,如清单 8 中所示。(您可以为开始四个问题提供自己的答案。)
清单 8. 使用 MEAN.JS Yeoman generator
$ mkdir test
$ sudo yo meanjs
.--------------------------.
`---------?
Welcome to Yeoman,
ladies and gentlemen!
'__________________________'
__'.___.'__
You're using the official MEAN.JS generator.
[?] What would you like to call your application?
[?] How would you describe your application?
Full-Stack JavaScript with MongoDB, Express, AngularJS, and Node.js
[?] How would you describe your application in comma separated key words?
MongoDB, Express, AngularJS, Node.js
[?] What is your company/author name?
Scott Davis
[?] Would you like to generate the article example CRUD module?
[?] Which AngularJS modules would you like to include?
ngCookies, ngAnimate, ngTouch, ngSanitize
在回答最后一个问题后,您会看到一系列行为,这是 NPM 在下载所有服务器端的依赖关系(包括 Express)。NPM 完成后,Bower 将下载所有客户端的依赖关系(包括 AngularJS、Bootstrap 和 jQuery)。
至此,您已经安装了 EAN 堆栈(Express、AngularJS 和 Node.js) — 目前只缺少 M (MongoDB)。如果现在输入 grunt 命令,在没有安装 MongoDB 的情况下启动应用程序,您会看到类似于清单 9 中的一条错误消息。
清单 9. 试图在没有 MongoDB 的情况下启动 MeanJS
events.js:72
// Unhandled 'error' event
Error: failed to connect to [localhost:27017]
at null.&anonymous&
(/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:546:74)
[nodemon] app crashed - waiting for file changes before starting...
如果启动应用程序时看到这条错误消息,请按下 Ctrl+C 键停止应用程序。
为了使用新的 MEAN 应用程序,现在需要安装 MongoDB。
安装 MongoDB
MongoDB 是一种 NoSQL 持久性存储。它不是使用 JavaScript 编写的,也不是 NPM 包。必须单独安装它才能完成 MEAN 堆栈的安装。
访问 ,下载平台特定的安装程序,并在安装 MongoDB 时接受所有默认选项。
安装完成时,输入 mongod 命令启动 MongoDB 守护程序。
MeanJS Yeoman 生成器已经安装了一个名为
的 MongoDB 客户端模块,您可以检查 package.json 文件来确认这一点。我将在后续的文章中详细介绍 MongoDB 和 Mongoose。
安装并运行 MongoDB 后,最终您可以运行您的 MEAN 应用程序并观察使用效果了。
运行 MEAN 应用程序
要启动新安装的 MEAN 应用程序,在运行 MeanJS Yeoman 生成器之前,一定要位于您创建的 test 目录中。在输入 grunt 命令时,输出内容应该如清单 10 中所示。
清单 10. 启动 MEAN.JS 应用程序
Running "jshint:all" (jshint) task
&& 46 files lint free.
Running "csslint:all" (csslint) task
&& 2 files lint free.
Running "concurrent:default" (concurrent) task
Running "watch" task
Waiting...
Running "nodemon:dev" (nodemon) task
[nodemon] v1.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: app/views/**/*.* gruntfile.js server.js config/**/*.js app/**/*.js
[nodemon] starting `node --debug server.js`
debugger listening on port 5858
NODE_ENV is not defined! Using default development environment
MEAN.JS application started on port 3000
模块(均由生成器进行安装)可以确保源代码在句法和语体上是正确的。 包监控文件系统中的代码修改情况,并在检测到有的情况下自动重启服务器,当开发人员需要快速而频繁地修改代码基础时,这可以极大地提高他们的效率。(nodemon 包只在开发阶段运行,要监测生产环境的变化,必须重新部署应用程序并重启 Node.js。)
按照控制台输出的提示,访问
并运行您的新 MEAN 应用程序。
图 4 显示了 MEAN.JS 示例应用程序的主页。
图 4. MEAN.JS 示例应用程序的主页
在菜单栏中单击 Signup 创建一个新的用户账号。现在填写 Sign-up 页面上的所有字段(如图 5 中所示),然后单击 Sign up。在后续的指南中,您可以通过 Facebook、Twitter 等启用 OAuth 登录
图 5. MEAN.JS 示例应用程序的 Sign-up 页面
现在,您的本地 MongoDB 实例中已经保存了一组用户证书,您可以开始撰写新的文章了。单击 Articles 菜单选项(当您登录之后才会显示出来),并创建一些示例文章。图 6 显示了 Articles 页面。
图 6. MeanJS 的文章页面
您已经创建了自己的第一个 MEAN 应用程序。欢迎加入!
在这篇指南中,您完成相当多的内容。安装 Node.js 并编写了第一个 Node.js 脚本。学习了模块并使用 NPM 安装了几个第三方模块。安装 Yeoman 并将它作为可靠的 Web 开发平台,其中包含一个搭建实用工具 (Yo),一个编译脚本 (Grunt),以及一个管理客户端依赖关系的实用工具 (Bower)。安装 MeanJS Yeoman 生成器,并使用它来创建第一个 MEAN 应用程序。安装 MongoDB 与 Node.js 客户端库 Mongoose。最后运行您的首个 MEAN 应用程序。
下一次,我们会详细了解示例应用程序的源代码,从而了解 MEAN 太阳系中的所有四颗行星 (MongoDB、Express、AngularJS 和 Node.js)是如何相互作用的。
本条目发布于。属于分类。作者是。
Mac OS X设定ssh config后,ssh连接其它服务器时提示“Too many authentication failures for xxxx”
ssh user@192.168.1.x -o PreferredAuthentications=password
本条目发布于。属于分类。作者是。
学习的过程勇于将自己放空,经验或许就是前进最大的阻碍。
本条目发布于。属于分类。作者是。
安装IntelliJ IDEA
安装Scala Plugin
下载Scala包
添加Scala的bin目录到PATH
运行scala检测
下载Lift包
选择进入lift目录,如lift-basic
运行./sbt,自动下载依赖包
在sbt控制台下运行gen-idea,生成IDEA的项目文件
用IDEA打开当前文件夹,载入项目
在sbt控制台下运行container:start,启动项目
http://127.0.0.1:8080查看项目
本条目发布于。属于分类。作者是。
xxx(输入参数)=&(lambda操作符)xxx(表达式或者语句块)
//x的类型省略了,编译器可以根据上下文推断出来,后面跟着的是表达式
delegate(int x){return x+1;}
//后面跟着的是语句块
x=&{return x+1;}
delegate(int x){return x+1;}
//输入参数也可以带类型,带类型后别忘记小括号哦
(int x) =& x+1
delegate(int x){return x+1;}
//也可以多个输入参数,逗号分隔,别忘记小括号
(x,y) =& x+y
delegate(int x,int y){return x+y;}
//无参的也行
delegate(){return 1;}
本条目发布于。属于分类。作者是。
本站采用CDN云加速服务
缩短网址服务
请输入一个长网址 :
Clicki提供分析统计服务}

我要回帖

更多关于 怎样使游戏不停止运行 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信