|
|
October 28 在Ubuntu中搭建一般的LAMP环境实在是太简单的一件事, 只需要: $sudo apt-get install apache2 php5 mysql-server libapache2-mod-php5 然而, 这样搭建出来的LAMP环境, PHP是通过Apache2的mod执行的, 这也就是软件包libapache2-mod-php5的作用. 通过mod执行的PHP有速度快, 方便等诸多优势.但是在其他方面诸如用户权限分离和使用动态虚拟主机创建等,都需要使用fastcgi模式来运行PHP。 在网上找到了一篇资料测试通过,拿出来给大家分享!具体操作入下: 首先, 删除libapache2-mod-php5, 因为没用了.$sudo a2dismod php5 $sudo apt-get remove libapache2-mod-php5 安装cgi版的php(自己会支持fcgi的)和apache2的action模块 $sudo apt-get install php5-cgi $sudo a2enmod actions 新建目录, 把安装的php5-cgi扔过去 $sudo mkdir /usr/local/php5-fcgi $sudo mkdir /usr/local/php5-fcgi/bin $sudo cp /usr/bin/php5-cgi /usr/local/php5-fcgi/bin/ 下面关键了, 总是出错的就是这了 在你的虚拟主机配置(sites-enabled那里)文件, <VirtualHost > 之内, 其他标签之外添加这些内容: ScriptAlias /fcgi-bin/ "/usr/local/php5-fcgi/bin/" Action php-fastcgi /fcgi-bin/php5-cgi AddHandler php-fastcgi .php AddType application/x-httpd-php .php <Location /fcgi-bin> Options FollowSymLinks ExecCGI </Location> 然后重启apache2, 完事. October 27 今天拿到一台安装有UBUNTU系统的服务器,MYSQL都是APT安装的,哎,老大安装机器的时候不知道怎么了,都不喜欢在MYSQL里设置密码,我哭~!然后尝试登陆,怎么也登陆不上去,各种修改MYSQL root密码的方法都用都不成,后来急得我把user表的数据库文件用编辑器打开来看。发现里面只有一个debian-sys-maint用户。当时差点没哭出来。难怪我使用安全模式登陆到 MYSQL没有发现其他的用户。 着下可有办法了。我先把一个正常能登陆(有没有设置密码都无所谓)的MYSQL的USER表文件CP到着个机器的数据库表文件目录里,然后修改文件权限,重启服务。此时提供会报错误~! error: 'Access denied for user 'debian-sys-maint'@'localhost' (using password: YES)' 不怕。数据还是能起来的。呵呵。正常登陆进去后就开始修改一下user表中的debian-sys-maint用户密码,传说因为是系统启动MYSQL的时候专用帐号,每次关闭和启动的时候密码都是新的,所以就会出现前面那个系统错误。修改了它就OK了。当前最新的密码应该在你系统的 vi /etc/mysql/debian.cnf # Automatically generated for Debian scripts. DO NOT TOUCH! [client] host = localhost user = debian-sys-maint password = 1orZidSkUO1iQtEF 《==这个 socket = /var/run/mysqld/mysqld.sock [mysql_upgrade] user = debian-sys-maint password = 1orZidSkUO1iQtEF socket = /var/run/mysqld/mysqld.sock basedir = /usr 执行如下MYSQL命令: SET PASSWORD FOR 'debian-sys-maint'@'localhost' = PASSWORD('你的密码'); 然后再重启MYSQL就发现错误没辣~~!搞定。 后话:发现咱老大也瞒懒的~~!怒~~! October 23 转载:http://blog.wu-boy.com/2007/08/20/119/ 自己在站内有写一篇 [apache] mod_cband 频宽限制,不过这套好像没有真对网站用 header「[PHP] header下载档案 搭配资料库」 吐出来的下载方式做限制,只能针对单存下载的连结做限制,所以自己爬文了一下,又找到了 Bandwidth Module 这个套件,Banwidth官方网,目前出到 mod_bw v0.8 说明档。 底下是针对 FreeBSD 安装方式,所以其他安装方法就参考上面的说明档了 cd /usr/ports/www/mod_bw/ make install clean 上面这样就安装好了,再来就是设定 mod_bw 了 apaceh 预设是关闭的,所以请把他打开 - ForceBandWidthModule [On|Off]
这个设定预设情形,他不会对每个要求限制,如果你把他打开,他就会对每个要求做限制 普通要求:AddOutputFilterByType MOD_BW text/html text/plain 打开设定:ForceBandWidthModule On - BandWidth [From] [bytes/s]
这个设定有2个参数,第一是from,第二是速度,第一你可以用整个ip位址,或者是network mask例如:192.168.0.0/24 or 192.168.0.0/255.255.255.0) or all。最后的all就是全部皆可,不限制 BandWidth localhost 10240 BandWidth 192.168.218.5 0 上面针对 localhost 给 10KB的速度,然后针对 192.168.218.5 不限制速度 在版本0.8还可以针对client端的瀏览器做限制 - BandWidth u:[User-Agent] [bytes/s]
你可以利用正规语法比对client端瀏览器 BandWidth "u:^Mozilla/5(.*)" 10240 BandWidth "u:wget" 102400 还蛮不错的功能 - MinBandWidth [From] [bytes/s]
BandWidth all 102400 MinBandWidth all 50000 The example above, will have a top speed of 100kb for the 1º client. If more clients come, it will be splitted accordingly but everyone will have at least 50kb (even if you have 50 clients) BandWidth all 50000 MinBandWidth all -1 上面这个例子是保证client端下载速度保证 50KB/s - LargeFileLimit [Type] [Minimum Size] [bytes/s]
这个专门是用来限制大型档案,譬如说影音档 avi wmv 之类的 还蛮好用的喔 LargeFileLimit .avi 500 10240 上面是说如果 avi档案超过500KB 就限制速度在 10KB 这个不用理他,不要随便调整他 这是错误讯息导向,比如说超过限制,你可以写个html档然后导向那边 ErrorDocument 510 /errors/maxconexceeded.html BandWidthError 510 - MaxConnection [From] [Max]
限制连线数目,这个还蛮好用的 限制所有连线速度无限,但是只能有20条连线 BandWidth all 0 MaxConnection all 20 限制无限制ip速度无限,连线数20,然后网域192.168.0.0/24的速度 10KB,连线数目5 BandWidth all 0 BandWidth 192.168.0.0/24 10240 MaxConnection all 20 MaxConnection 192.168.0.0/24 5 然后在举一些官方的例子 Limit every user to a max of 10Kb/s on a vhost : <Virtualhost *> BandwidthModule On ForceBandWidthModule On Bandwidth all 10240 MinBandwidth all -1 Servername www.example.com </Virtualhost> Limit al internal users (lan) to 1000 kb/s with a minimum of 50kb/s , and files greater than 500kb to 50kb/s. <Virtualhost *> BandwidthModule On ForceBandWidthModule On Bandwidth all 1024000 MinBandwidth all 50000 LargeFileLimit * 500 50000 Servername www.example.com </Virtualhost> 限制 avi 跟 mpg 速度 20kb/s. <Virtualhost *> BandwidthModule On ForceBandWidthModule On LargeFileLimit .avi 1 20000 LargeFileLimit .mpg 1 20000 Servername www.example.com </Virtualhost> Using it the "right" way, with output filter by mime type (for text) to 5kb/s: <Virtualhost *> BandwidthModule On AddOutputFilterByType MOD_BW text/html text/plain Bandwidth all 5000 Servername www.example.com </Virtualhost> FTP目录和PHP服务目录分离,但整合在一个域名之下 要求: 一、FTP和WEBPHP程序分离不同的目录,且必须在同一个域名之下 二、FTP用户上传的PHP程序不能被执行。 三、大众用户下载FTP内的软件通过WEB的HTTP协议下载,下载需要进行下载限速。 四、防止外网盗链和讯雷盗链 软件列表: 1、apache2 2、MYSQL5 3、PHP5 4、PROFTPD-MYSQL(通过MYSQL限制进行磁盘配额) 5、UBUNTU 8 (软件安装的步骤我不在此进行说明,在我的BLOG其他日志中有详细的步骤,我只针对以上的一些特定软件和要求解决方法进行说明) 具体步骤入下: 一、FTP和WEBPHP程序分离不同的目录,且必须在同一个域名之下 网站的主目录为 /var/www/www.site.com FTP的主目录为 /var/ftp/[用户名]/文件目录 在www.site.com虚拟主机的配置文件中使用 Alias "soft" "/var/ftp" 二、FTP用户上传的PHP程序不能被执行。 然后增加一下代码用于限制PHP解释,防止FTP用户上传恶意PHP程序并执行 “php_admin_flag engine off” 代码如下: <Directory "/var/ftp/"> php_admin_flag engine off Options -Indexes AllowOverride ALL Order allow,deny Allow from all </Directory> 三、大众用户下载FTP内的软件通过WEB的HTTP协议下载,下载需要进行下载限速。 对于APACHE2的用户访问限制我在这里使用的是mod_bw模块,通过APXS2进行安装。首先要确定该APACHE2服务内是否安装有MOD_BW模块。(有没有装自己心理明白,呵呵!)先对apxs2进行检查,执行: $ apxs2 如果出现提示是未知的命令说明你还没有安装。 接下来便开始安装apxs2,先检查自己的APT是否是最新的 $ apt-get update 安装apxs2 $ apt-get install apache2-prefork-dev 安装gcc $ apt-get install gcc 去mod_bw的官网下在最新的版本,解压后修改mod_bw.c内的代码: 将原本的: /* Compatibility for ARP < 1 */ #if (APR_MAJOR_VERSION < 1) #define apr_atomic_inc32 apr_atomic_inc #define apr_atomic_dec32 apr_atomic_dec #define apr_atomic_add32 apr_atomic_add #define apr_atomic_cas32 apr_atomic_cas #define apr_atomic_set32 apr_atomic_set #endif 改成: /* Compatibility for ARP < 1 */ /* #if (APR_MAJOR_VERSION < 1) #define apr_atomic_inc32 apr_atomic_inc #define apr_atomic_dec32 apr_atomic_dec #define apr_atomic_add32 apr_atomic_add #define apr_atomic_cas32 apr_atomic_cas #define apr_atomic_set32 apr_atomic_set #endif */ 执行模组安装 $ apxs2 -i -a -c mod_bw.c 安装末尾提示如下信息: ---------------------------------------------------------------------- Libraries have been installed in: /usr/lib/apache2/modules
If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to `/etc/ld.so.conf' See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- chmod 644 /usr/lib/apache2/modules/mod_bw.so [activating module `bw' in /etc/apache2/httpd.conf] 这时就会安装到你的Apache的模组里,并且http.conf也已经自动加上了: LoadModule bw_module modules/mod_bw.so 则表明安装成功! 建立mod_bandwidth工作目录 root# mkdir -p /tmp/apachebw/link root# mkdir -p /tmp/apachebw/master root# chown -R nobody:nobody /tmp/apachebw root# chmod -R 755 /tmp/apachebw 在<Directory "/var/ftp/">处添加如下信息,可根据自己的需要进行修改 # Limit BW usage BandWidthModule On ForceBandWidthModule On #開放20KB对外使用 BandWidth all 51200 #每Connection最小带宽为50K MinBandwidth all 51200 #大于50M的文件传输速率按50Kbytes/sec #LargeFileLimit 51200 51200 #最大同时连接数量 #MaxConnection 300 把Apache服务器重新启动就可以实现对带宽的限制了。
四、防止外网盗链和讯雷盗链 在对于盗链方面还没有比较好的解决思路,基本上都是通过PHP的HEADER跳转前进行referer的检查,和使用rewrite的效验,通过浏览器访问的话盗链基本没问题,但是如果将最终的URL拷贝到下载软件上,下载软件直接跳过任何效验进行下载了。 使用权限 : 所有使用者 使用方式 : chmod [-cfvR] [--help] [--version] mode file... 说明 : Linux/Unix 的档案调用权限分为三级 : 档案拥有者、群组、其他。利用 chmod 可以藉以控制档案如何被他人所调用。 参数 : mode : 权限设定字串,格式如下 : [ugoa...][[+-=][rwxX]...][,...],其中 u 表示该档案的拥有者,g 表示与该档案的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。 + 表示增加权限、- 表示取消权限、= 表示唯一设定权限。 r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该档案是个子目录或者该档案已经被设定过为可执行。 -c : 若该档案权限确实已经更改,才显示其更改动作 -f : 若该档案权限无法被更改也不要显示错误讯息 -v : 显示权限变更的详细资料 -R : 对目前目录下的所有档案与子目录进行相同的权限变更(即以递回的方式逐个变更) --help : 显示辅助说明 --version : 显示版本 范例 :将档案 file1.txt 设为所有人皆可读取 : chmod ugo+r file1.txt 将档案 file1.txt 设为所有人皆可读取 : chmod a+r file1.txt 将档案 file1.txt 与 file2.txt 设为该档案拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入 : chmod ug+w,o-w file1.txt file2.txt 将 ex1.py 设定为只有该档案拥有者可以执行 : chmod u+x ex1.py 将目前目录下的所有档案与子目录皆设为任何人可读取 : chmod -R a+r * 此外chmod也可以用数字来表示权限如 chmod 777 file 语法为:chmod abc file 其中a,b,c各为一个数字,分别表示User、Group、及Other的权限。 r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。
范例: chmod a=rwx file 和 chmod 777 file 效果相同 chmod ug=rwx,o=x file 和 chmod 771 file 效果相同 若用chmod 4755 filename可使此程序具有root的权限
October 19 什么是sitemap?简单的说,就是一个xml文件,定义了你网站“主要栏目”的结构,以方便搜索引擎更好的建立索引和抓取文件。是对一些从其他页面不怎么链接得到的页面尤其有用,更详细的信息可以查阅Wikipedia上的说明。 Google是支持sitemap的,Google帮助中的How do I create a Sitemap file?一文列举了一些生成sitemap的方式和工具,我采取的是第一种——sitemap protocol方式,详细说明在这里,英文好的朋友可以直接去啃,不用看我在下面罗嗦了。 第一步,准备工作 由于Google Sitemap Generator是使用python语言编写的,所以需要python 2.2以上的版本支持,其余的要求如要有文件的访问权等等不再详述。由于我的操作系统是Ubuntu(推荐),所以python支持也没问题。 从http://www.sourceforge.net/project/showfiles.php?group_id=137793&package_id=153422下载Google Sitemap Generator的程序文件,在本机建一个目录把它解压缩。 第二步,创建配置文件 把刚才解压缩得到的example_config.xml文件另存为config.xml,并编辑之: <site base_url=”http://www.daemon.com/” store_into=”/var/www/docroot/sitemap.xml.gz” verbose=”1″ > 其中base_url是网站地址,store_into是sitemap文件的地址,最好使用绝对路径,于是上面的内容修改为: <site base_url=”http://www.daemon.com/” store_into=”/var/www/sitemap.xml” verbose=”1″ > 接下来修改** MODIFY or DELETE **开头的sitemap生成方式定义部分,要删除掉不打算使用的生成方式,按照xml语法标签来分,生成方式有以下几种: - url,网页地址,附加定义为最后修改时间,更新周期,优先级,个人认为这种方式比较麻烦。
- urllist,通过一个包含网页地址列表的文件,可以定义文件优先级,个人认为这种方式还不如直接使用urllist文件省事。
- directory,文件地址,附加定义为文件、对应网址、默认索引页,个人认为这种方式比较适合我们,因为在本机一般都会有一套比较完整的网站文件,用他们来生成sitemap再合适不过了。
- accesslog,网站日志文件,有必要么?
- sitemap,sitemap节点文件,主要用于把多个分散的sitemap文件集合起来。
在这里我们删除掉其他的方式,只保留directory方式,并对其进行修改,结果如下: <directory path=”你的网站物理路径” 例如:/var/www/www.daemon.com/ url=”http://www.daemon.com/” default_file=”index.html” *默认文件* /> <directory path=”你的网站物理路径” 例如:/var/www/www.daemon.com/channel/ url=”http://www.daemon.com/channel/” *你的子栏目目录,如果子栏目有独立的目录* default_file=”index.html” *默认文件* /> 注意一般简单的网站只要有一个directory就可以了,但也可以有多个directory段,仅当你的网站是用子目录来划分栏目,也就是对应到本机不一定放在一个目录下调试的情况下才建议使用。可以用default_file来定义首页文件。 接下来修改FILTERS段,索引文件过滤部分。过滤规则是自上而下匹配的,匹配动作action有两种drop和pass,drop明确不索引文 件,pass则是索引文件(但也有可能被后面的规则排除),匹配规则type可以是wildcard或者regexp,wildcard是使用通配符* 和?来匹配文件,regexp自然就是正则表达式了。注意默认的匹配动作是drop不索引文件,所以要想简单的索引所有文件,这一段留空就可以了。 <filter action=”drop” type=”wildcard” pattern=”*/cert/*” /> 这里我只简单的屏蔽掉信息产业部备案文件保存的那个目录,注意pattern是要和完整的网址进行匹配,略微不同于apache conf文件中的rewrite规则写法。 第三步,运行Google Sitemap Generator python sitemap_gen.py --config=</var/www/www.daemon.com/config.xml> 运行成功后系统会出现一下内容: Reading configuration file: /var/www/www.daemon.com/config.xml The Sitemap type is WEB Sitemap. Walking DIRECTORY "/var/www/www.daemon.com/" Walking DIRECTORY "/var/www/www.daemon.com/html/" Walking DIRECTORY "/var/www/www.daemon.com/html/video/" Walking DIRECTORY "/var/www/www.daemon.com/html/films/" Sorting and normalizing collected URLs. Writing Sitemap file "sitemap.xml" with 10953 URLs Notifying search engines. Notifying: www.google.com Count of file extensions on URLs: 1 (no extension) 1680 .gif 3944 .html 3475 .jpg 10 .php 2 .py 1 .swf 1738 .txt 2 .xml 100 / Number of errors: 0 Number of warnings: 0 最后,登录Google Webmaster Tools提交你的sitemap文件即可。 October 18 在Linux下对IDE的设备是以hd命名的,第一个ide设备是hda,第二个是hdb,依此类推。SCSI接口设备是用sd命名的,第一个设备是 sda,第二个是sdb,依此类推。分区是用设备名称加数字命名的。例如hda1代表hda这个硬盘设备上的第一个分区,hda2代表hda这个硬盘设备上的第二个分区。linux下对分区的编号,第一个主分区为1,其次为2,3,最大为4,扩展盘上的逻辑分区从5开始。 新添加的硬盘可以在/dev下找到,下面以新加的一块SCSI硬盘/dev/sdb为例说明。首先用fdisk进行分区。 #fdisk /dev/sdb 进入fdisk模式。可以用m命令来看fdisk命令的内部命令;n命令创建一个新分区;d命令删除一个存在的分区;p命令显示分区列表;t命令修改分区的类型ID号;l命令显示分区ID号的列表;a命令指定启动分区;w命令是将对分区表的修改存盘让它发生作用。 Command (m for help):p //查看新硬盘的分区 Command (m for help):n //创建新分区 Command action e extended //输入e为创建扩展分区 p primary partition (1-4) //输入p为创建主分区,这里我们选择p Partion number(1-4):1 //第一个扩展分区,按你需求可以最多分4个主分区 First Cylinder(1-1014,default 1): 1 //第一个主分区起始的磁盘块数 Last cylindet or +siza or +sizeM or +sizeK: +1024MB //可以是以MB为单位的数字 这样我们就创建完一个分区,如果要创建更多分区可以照上面的步骤继续创建。如果要创建扩展分区,就按n,e。扩展分区本身没有办法使用,必须要在扩展分区内再建逻辑分区,操作是n,l。经过多步操作,硬盘被划分成如下分区状况: Device Boot Start End Blocks Id System /dev/sdb1 1 100 102384 83 Linux /dev/sdb2 101 200 102400 83 Linux /dev/sdb3 201 307 109568 5 Extended /dev/sdb5 201 260 61424 83 Linux /dev/sdb6 261 307 48112 83 Linux 其中sdb1,sdb2都是主分区,sdb3是扩展分区,在扩展分区中建了两个逻辑分区,分别是sdb5和sdb6。创建完后用w保存分区。 Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks. 这样就分区完,我们还要进行格式化: mkfs.ext3 /dev/sdb1 或者 #mkfs -t ext3 -c /dev/sdb1 //如果有多个分区,则分区修改为sdb2这样 扩展分区不能直接格式化,需要单独格式化各个逻辑分区。格式化完后我们需要进行挂载分区。 #mkdir /var/www //创建/www目录,我们将把新的分区挂到www下 #mount /dev/sdb1 /var/www //将/dev/sdb1挂载到/var/www # df //用df命令进行查看 Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 3771316 1388956 2190788 39% / /dev/sda1 101089 9463 86407 10% /boot none 62988 0 62988 0% /dev/shm /dev/sdb1 485906 8239 452580 2% /var/www //看到了,这就是我们刚才新挂载的分区 要挂载其他分区操作同上。到这里我们工作已接近尾声了,不过我们如果这样就结束的话,我们每次重新启动服务器后都要进行手工挂载,这样很麻烦,我们需要修改/etc/fstab文件来进行自动挂载。 vi /etc/fstab 添加 /dev/sdb1 /var/www ext3 defaults 1 1 附分区表/etc/fstab格式简介: linux在引导过程中用该表来按不同的方式装载分区和目录。每个文件系统有几个相干的参数,这些参数确定文件系统如何读取、文件系统有哪些相关用户权限等。 该表一般包含6个字段。 <file system>(有的系统用label表示) 要装载的分区(如/dev/hda2)和文件系统(如/usr) <dir> (或者mount point等) 要装载的分区和文件系统所在目录 <type>(或format等) 文件系统格式类型,如ext3,vfat <options>(mount options等) 其值为defaults时,即默认选项,包括参数rw(读写)、suid(SUID权限)、exec(二进制可执行文件)、auto(系统起动时自动装载)、nouser(只有根用户可以装载,相反为user)、async(数据异步读写)),其它的参数还有umask,unhide(hide), iocharset(语言环境)等,当然你可以自己指定各个值。 <dump>(dump value) dump(英文意为倾倒垃圾)时是否需要BACKUP的标志位,其内定值是0。1表示文件系统自动写入磁盘。 <pass>(Filesystem Check Order) 设定此filesystem是否要在开机时做check的动作,除了root的filesystem其必要的check为1之外,其它皆可视需要设定,内定值是0。 例子:如果你有windows分区(fat32)在/dev/hda1处,你想在系统启动时就自动挂载该分区,并且挂载过来之后一般用户可读可写,并且可以显示中文。则在fstab中添加: /dev/hda1 /mnt/c vfat umask=000,iocharset=gb2312 0 0 October 14 安装mysql和phpmyadmin,其中phpmyadmin不是必需的 # apt-get install mysql-server mysql-client libmysqlclient15-dev phpmyadmin apache2 为mysql设置root密码 # mysqladmin -u root password yourrootsqlpassword 如果需要其他人访问本机的mysql,同样需要设置密码 # mysqladmin -h server1.example.com -u root password yourrootsqlpassword 安装带mysql支持的proftpd,注意选择proftpd工作在standalone模式 # apt-get install proftpd-mysql 建立虚拟用户组,这个是为了把proftpd用户虚拟到本机的一个用户上。注意下面的2001修改为自定义的。 # groupadd -g 2001 ftpgroup # useradd -u 2001 -s /bin/false -d /bin/null -c "proftpd user" -g ftpgroup ftpuser 建立proftpd使用的mysql数据库ftp,并创建数据表。 mysql> create database ftp; 为proftpd访问数据创建的帐号 mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost' IDENTIFIED BY 'password'; mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON ftp.* TO 'proftpd'@'localhost.localdomain' IDENTIFIED BY 'password'; 创建ftpgroup表 CREATE TABLE ftpgroup( groupname varchar(16) NOT NULL default '', gid smallint(6) NOT NULL default '5500', members varchar(16) NOT NULL default '', KEY groupname (groupname) ) TYPE=MyISAM; CREATE TABLE ftpquotalimits ( name varchar(30) default NULL, quota_type enum('user','group','class','all') NOT NULL default 'user', per_session enum('false','true') NOT NULL default 'false', limit_type enum('soft','hard') NOT NULL default 'soft', bytes_in_avail int(10) unsigned NOT NULL default '0', bytes_out_avail int(10) unsigned NOT NULL default '0', bytes_xfer_avail int(10) unsigned NOT NULL default '0', files_in_avail int(10) unsigned NOT NULL default '0', files_out_avail int(10) unsigned NOT NULL default '0', files_xfer_avail int(10) unsigned NOT NULL default '0' ) TYPE=MyISAM;
CREATE TABLE ftpquotatallies ( name varchar(30) NOT NULL default '', quota_type enum('user','group','class','all') NOT NULL default 'user', bytes_in_used int(10) unsigned NOT NULL default '0', bytes_out_used int(10) unsigned NOT NULL default '0', bytes_xfer_used int(10) unsigned NOT NULL default '0', files_in_used int(10) unsigned NOT NULL default '0', files_out_used int(10) unsigned NOT NULL default '0', files_xfer_used int(10) unsigned NOT NULL default '0' ) TYPE=MyISAM; CREATE TABLE ftpuser ( id int(10) unsigned NOT NULL auto_increment, userid varchar(32) NOT NULL default '', passwd varchar(32) NOT NULL default '', uid smallint(6) NOT NULL default '5500', gid smallint(6) NOT NULL default '5500', homedir varchar(255) NOT NULL default '', shell varchar(16) NOT NULL default '/sbin/nologin', count int(11) NOT NULL default '0', accessed datetime NOT NULL default '0000-00-00 00:00:00', modified datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (id), UNIQUE KEY userid (userid) ) TYPE=MyISAM; 修改/etc/proftpd/proftpd.conf 在<IfModule mod_sql.c>中增加以下代码: # The passwords in MySQL are encrypted using CRYPT SQLAuthTypes Plaintext Crypt SQLAuthenticate users groups # used to connect to the database # databasename@host database_user user_password SQLConnectInfo ftp@localhost proftpd password # Here we tell ProFTPd the names of the database columns in the "usertable" # we want it to interact with. Match the names with those in the db SQLUserInfo ftpuser userid passwd uid gid homedir shell # Here we tell ProFTPd the names of the database columns in the "grouptable" # we want it to interact with. Again the names match with those in the db SQLGroupInfo ftpgroup groupname gid members # set min UID and GID - otherwise these are 999 each SQLMinID 500 # create a user's home directory on demand if it doesn't exist SQLHomedirOnDemand on # Update count every time user logs in SQLLog PASS updatecount SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" ftpuser # Update modified everytime user uploads or deletes a file SQLLog STOR,DELE modified SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" ftpuser 在<IfModule mod_quotatab.c>中增加一下代码: # User quotas # =========== QuotaEngine on QuotaDirectoryTally on QuotaDisplayUnits Mb QuotaShowQuotas on SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, files_xfer_avail FROM ftpquotalimits WHERE name = '%{0}' AND quota_type = '%{1}'" SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM ftpquotatallies WHERE name = '%{0}' AND quota_type = '%{1}'" SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" ftpquotatallies SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" ftpquotatallies QuotaLimitTable sql:/get-quota-limit QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally RootLogin off RequireValidShell off 分别增加日志 QuotaLog "/var/log/proftpd.quota.log" SQLLogFile /var/log/proftpd.sql.log 录入测试用户数据 INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES ('ftpgroup', 2003, 'ftpuser'); INSERT INTO `ftpquotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES ('test', 'user', 'true', 'hard', 15728640, 0, 0, 0, 0, 0); INSERT INTO `ftpuser` (`id`, `userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES(1, 'test', 'test123', 2001, 2001, '/home/www.example.com', '/sbin/nologin', 0, '', ''); 注意:如果的你的proftpd版本大于1.3.0的话 SQLHomedirOnDemand 需要改用 CreateHome来代替!
name: - 用户帐号 quota type: - user, group, class, all (we use user) per_session: - true or false (we use true) limit_type: - 硬限制 or 软限制 (我们一般用硬限制) bytes_in_avail: - 允许上传的字节数 bytes_out_avail: - 允许下载的字节数 bytes_xfer_avail: - 允许传输的字节数(包括上传/下载) files_in_avail: - 允许上传的文件数 files_out_avail: - 允许下载的文件数 files_xfer_avail: - 允许传输的文件数(包括上传/下载) 一基本配置 1. /etc/apt/sources.list文件的基本格式: deb http://site.http.org/debian distribution section1 section2 section3 deb-src http://site.http.org/debian distribution section1 section2 section3 deb 二进制程序包 deb-src 原代码程序包 例如: deb http://http.us.debian.org/debian stable main contrib non-free deb-src http://non-us.debian.org/debian-non-US stable non-US deb http://non-us.debian.org/debian-non-US stable/non-US main contrib non-free deb-src http://http.us.debian.org/debian stable main contrib non-free apt 会忽略以"#"开头的行 注意: 修改/etc/apt/sources.list后,应及时更新数据库列表 2.制作本地apt # mkdir /root/debs 将自己收集的.deb包考入/root/debs目录 # dpkg-scanpackages debs| gzip > debs/Packages.gz 在/etc/apt/sources.listdeb 加入: file:/root debs/ 3.寻找速度最快的下载镜相:netselect, netselect-apt 安装netselect软件包 # apt-get install netselect 测试我使用的镜像 # netselect security.debian.org ftp.us.debian.orgftp.jp.debian.org non- us.debian.org people.debian.org gluck.debian.org 520 ftp.jp.debian.org # 看到了我所使用的镜像中 ftp.jp.debian.org速度最快 得分为520 (得分越低越好) 你可以在这里查找debian的镜像列表 http://www.debian.org/mirror/mirrors_full 你也可以用netselect-apt下载列表 # ls sources.list ls: sources.list: File or directory not found # netselect-apt stable (...) # ls -l sources.list sources.list # 前提是你已经安装并运行了'wget'包 4.把CD-ROM加入到你的/etc/apt/sources.list文件 如果使用apt自动从CD-ROM上安装软件或升级系统,可以把它加 入/etc/apt/sources.list文件 # apt-cdrom add 注: CD-ROM必须在/etc/fstab文件中已正确配置 二、管理包 1.apt系统使用一个数据库列表来记录系统已经安装了哪些软件,哪些没有安装,哪 些软件可以通过apt系统自动安装 apt-get通过分析这个数据库来决定如何安装软件 , 应该经常运行#apt-get update来更新此数据库 2.安装软件包 # apt-get install packagename apt-get的参数 -h This help text. -d Download only - do NOT install or unpack archives -f Attempt to continue if the integrity check fails -s No-act. Perform ordering simulation -y Assume Yes to all queries and do not prompt -u Show a list of upgraded packages as well 软件包会被下载到/var/cache/apt/archives 稍后进行安装 如果一个软件包坏了,或者你只是想重新安装一个软件的最新版本 ,可以使用-- reinstall参数,如 # apt-get --reinstall install gdm 在安装软件时,可以用apt-get install package/distribution或apt-get install package=version来指定软件的安装版本,如 # apt-get install nautilus/unstable 3.移除软件包 apt-get remove package # apt-get remove gnome-panel 这样就会移除gnome-panel以及对gnome-panel有依赖性的软件包,无法使用apt系统 仅仅移除此软件,而保留对它有依赖性的软件包。 apt-get remove package并不能移除这些软件的配置文件 # apt-get --purge remove gnome-panel(这个很常用,注意前面是两横哟!) 就可以一块把他的配置文件移除 4.升级软件包 apt-get upgrade 5.升级到一个新的版本 # apt-get -u dist-upgrade 6.移除无用的软件包 当安装软件时,软件包会被先下载到/var/cache/apt/archives/目录下,然后安装 。这样这个目录所占空间会越来越大,幸运的是apt提供了相应的管理工具 apt-get clean删除/var/cache/apt/archives/ 和 /var/cache/apt/archives/partial/目录下所有包(锁定的除外)。 apt-get autoclean仅删除不再能被下载的包 7. 8.如何维持一个混合的系统 鉴于testing版unstable版本比稳定,又比stable版本要新 ,很多人使用testing,可 是有些人想运行某个软件的最新版,却又不愿把这个系统升级为unstable,即想使用 一个混合的系统,那么可以这样做: 在 /etc/apt/apt.conf 加入: APT::Default-Release "testing"; 当要安装unstable软件时 加 -t 参数: # apt-get -t unstable install packagename 注:不要忘记在/etc/apt/sources.list中加入相应的源 9.从一个特定的debian版本升级软 # apt-get install `apt-show-versions -u -b | grep unstable`件 10.如何在软件升级时避免特定软件不会被升级 如果你使用的bebian版本在2.2以上,仅仅需要修改/etc/apt/preferences 文件 格式非常简单: Package: Pin: Priority: 例如我要保持gaim的0.58版本 只需加上: Package: gaim Pin: version 0.58* 统配符 * 指锁定以0.58开头的所有版本 这就是说即使存在0.58-1 或类似 也不会 被安装 Priority(优先级)是可选项 默认 989 <0 此软件永不会被安装 0~100 软件不被安装,不是有效的版本 >100 此软件会被安装 即 如果有更新版本,软件会被升级 100~1000 软件不会被降级安装,例如:我安装的gaim 0.59 , 锁定gaim 0.58 ,优先 级为999 那么0.58就不会被安装 ,如果要降级安装 则优先级许大于 1000 获取软件信息 1.搜寻软件名 # apt-cache search gaim 软件信息 # apt-cache show gaim 如果已经安装,并且又有了新版本,那么都会显示,安装版本在后 获取更多信息 # apt-cache showpkg gaim 查询软件的依赖性 # apt-cache depends gaim 2.用dpkg查询软件名 根据某一个文件查询软件名 # dpkg -S stdio.h 3.询问式安装 # auto-apt run command 4.查询文件的归属 # apt-file search filename 就象dpkg -S 但可以查询,但可以查未安装软件包 也可以查询一个包所含文件 # apt-file list packagename 它会用到数据库所以要及时更新 # apt-file update 程序源文件 1.下载程序源码 # apt-get source packagename 这样就会下载三个文件 a .orig.tar.gz, a .dsc 和 a .diff.gz 下载后自动打包 # apt-get -b source packagename 2.编译软件 # apt-get build-dep gmc 下载所编译包的依赖程序 October 13 顶!我常用的。打开 /etc/apt/sources.list
deb http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe multiverse deb http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse deb http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse deb http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe multiverse deb http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse deb-src http://ubuntu.cn99.com/ubuntu/ hardy main restricted universe multiverse deb-src http://ubuntu.cn99.com/ubuntu/ hardy-security main restricted universe multiverse deb-src http://ubuntu.cn99.com/ubuntu/ hardy-updates main restricted universe multiverse deb-src http://ubuntu.cn99.com/ubuntu/ hardy-proposed main restricted universe multiverse deb-src http://ubuntu.cn99.com/ubuntu/ hardy-backports main restricted universe multiverse deb http://ubuntu.cn99.com/ubuntu-cn/ hardy main restricted universe multiverse
然后在
# apt-get update && apt-get upgrade
1. 安装SVN apt-get install subversion 2. 建立svn仓库 1). 建立svn目录:mkdir /home/.svn(使用隐藏目录) 2). cd /home/.svn 3). mkdir astar 4). 创建仓库astar:svnadmin create /home/.svn/astar,执行完毕后astar目录有svnadmin创建的目录和文件 5). mkdir test 6). 创建仓库test:svnadmin create /home/.svn/test,执行完毕后test目录有svnadmin创建的目录和文件 3. 配置和管理svn 1). 每个仓库的配置文件在$repos/conf/下,vi svnserve.conf,配置项在[general]下: anon-access:匿名用户的权限,可以为read,write和none,默认值read。不允许匿名用户访问:anon-access = none auth-access:认证用户的权限,可以为read,write和none,默认值write。 password-db:密码数据库的路径,去掉前边的# authz-db:认证规则库的路径,去掉前边的#。 注意:这些配置项的行都要顶格,否则会报错。修改配置后需要重启svn才能生效。 2). 配置passwd文件 这是每个用户的密码文件,比较简单,就是“用户名=密码”,采用的是明码。如allen=111111 3). 配置authz文件 1. [groups] section:为了便于管理,可以将一些用户放到一个组里边,比如:owner=allen,ellen 2. groups下边的sections表示对一个目录的认证规则,比如对根目录的认证规则的section为[/]。设置单用户的认证规则时一个用户一行,如: [/] allen=rw #allen对根目录的权限为rw ellen=r #ellen对根目录的权限为r 如果使用group,需要在group名字前加@,如 @owner=rw #group owner中的用户均为rw,等价于上边的两句话 启动时如果从/home/.svn/astar启动,/就是astar目录,用如上方式以astar目录为根设置权限。 如果从/home/.svn/启动,每个仓库根还是自己的起始目录。可以采用如上方式设置astar的权限,也可以采用如下方式: [astar:/] @owner=rw 设置test的权限如下: [test:/] @harry_and_sally = rw 简言之,每个仓库的根目录(/)就是自己的起始目录;[repos:/]这种方式只适用于多仓库的情况;[/]适合于单仓库和单仓库的方式。 3. 不能跨越仓库设置权限。 4. 启动和停止svn 1). 启动: 1. 从astar目录启动,svnserve -d -r /home/.svn/astar,根目录(/)是astar,authz中规则的配置使用section[/]。访问方式为: svn://192.168.0.87/ 2. 从.svn目录启动,svnserve -d -r /home/.svn,根目录(/)是.svn,authz中对astar的配置使用section[astar:/] ,对test的配置使用section[test:/]。访问方式为: svn://192.18.0.87/astar svn://192.18.0.87/test 如果需要svn自启动,把命令加入/etc/rc.local中 2). 检查svn服务器是否已经启动(svn默认使用3690端口):netstat -an | grep 3690 3). 停止:killall svnserve 5. svn client 在checkout的情况下出现类似提示: svn: Can't convert string from 'UTF-8' to native encoding 解决的办法是在root权限下在任何目录下执行LANG="zh_CN.UTF-8"这真是一个不是问题的问题,可能是为了方便将语言格式改成E文造成的 October 04 第一部分的函数我测试了utf-8的编码没有出现问题,估计是测试不够变态,呵呵!不过经过以后的测试我会对本文章进行修改! 第一部分 ------------------------------------------------------------------------------------ 程序一:PHP截取中文字符串方法 由于网站首页以及vTigerCRM里经常在截取中文字符串时出现乱码(使用substr),今天找到一个比较好的截取中文字符串方法,在此与大家共享。 function msubstr($str, $start, $len) { $tmpstr = ""; $strlen = $start + $len; for($i = 0; $i < $strlen; $i++) { if(ord(substr($str, $i, 1)) > 0xa0) { $tmpstr .= substr($str, $i, 2); $i++; } else $tmpstr .= substr($str, $i, 1); } return $tmpstr; } 程序二:PHP截取UTF-8字符串,解决半字符问题 /****************************************************************** * PHP截取UTF-8字符串,解决半字符问题。 * 英文、数字(半角)为1字节(8位),中文(全角)为3字节 * @return 取出的字符串, 当$len小于等于0时, 会返回整个字符串 * @param $str 源字符串 * $len 左边的子串的长度 ****************************************************************/ function utf_substr($str,$len) { for($i=0;$i<$len;$i++) { $temp_str=substr($str,0,1); if(ord($temp_str) > 127) { $i++; if($i<$len) { $new_str[]=substr($str,0,3); $str=substr($str,3); } } else { $new_str[]=substr($str,0,1); $str=substr($str,1); } } return join($new_str); } ?> php utf-8 字符串截取 <? function cutstr($string, $length) { preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/", $string, $info); for($i=0; $i<count($info[0]); $i++) { $wordscut .= $info[0][$i]; $j = ord($info[0][$i]) > 127 ? $j + 2 : $j + 1; if ($j > $length - 3) { return $wordscut." ..."; } } return join('', $info[0]); } $string="242432反对感是456犯得上广泛大使馆地方7890"; for($i=0;$i<strlen($string);$i++) { echo cutstr($string,$i)."<br>"; } ?> 截取utf-8字符串函数 为了支持多语言,数据库里的字符串可能保存为UTF-8编码,在网站开发中可能需要用php截取字符串的一部分。为了避免出现乱码现象,编写如下的UTF-8字符串截取函数 关于utf-8的原理请看 [url=http://www.allosoft.com/bB2/viewtopic.php?t=13][color=#0000ff]UTF-8 FAQ[/color][/url] UTF-8编码的字符可能由1~3个字节组成, 具体数目可以由第一个字节判断出来。(理论上可能更长,但这里假设不超过3个字节) 第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符 第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符 否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)。 以前为某网站设计的代码(也是现在用在首页的长度截取的函数) [b]Code:[/b] <?php // Cut_Str; //$sourcestr 是要处理的字符串 //$cutlength 为截取的长度(即字数) function cut_str($sourcestr,$cutlength) { $returnstr=''; $i=0; $n=0; $str_length=strlen($sourcestr);//字符串的字节数 while (($n<$cutlength) and ($i<=$str_length)) { $temp_str=substr($sourcestr,$i,1); $ascnum=Ord($temp_str);//得到字符串中第$i位字符的ascii码 if ($ascnum>=224) //如果ASCII位高与224, { $returnstr=$returnstr.substr($sourcestr,$i,3); //根据UTF-8编码规范,将3个连续的字符计为单个字符 $i=$i+3; //实际Byte计为3 $n++; //字串长度计1 } elseif ($ascnum>=192) //如果ASCII位高与192, { $returnstr=$returnstr.substr($sourcestr,$i,2); //根据UTF-8编码规范,将2个连续的字符计为单个字符 $i=$i+2; //实际Byte计为2 $n++; //字串长度计1 } elseif ($ascnum>=65 && $ascnum<=90) //如果是大写字母, { $returnstr=$returnstr.substr($sourcestr,$i,1); $i=$i+1; //实际的Byte数仍计1个 $n++; //但考虑整体美观,大写字母计成一个高位字符 } else //其他情况下,包括小写字母和半角标点符号, { $returnstr=$returnstr.substr($sourcestr,$i,1); $i=$i+1; //实际的Byte数计1个 $n=$n+0.5; //小写字母和半角标点等与半个高位字符宽... } } if ($str_length>$cutlength){ $returnstr = $returnstr . "...";//超过长度时在尾处加上省略号 } return $returnstr; } --------------------------------------------------------------------------------- 第二部分 ---------------------------------------------------------------------------------- 后来在论坛上看到有朋友提出更新的意见,代码如下: [code]// 切断文字列(以上长度时用...表示) function cut_str($msg,$cut_size,$charset="UTF-8",$suffix="...") { if($cut_size<=0) return $msg; $i=1;$han=0;$eng=0; while ($i <= strlen($msg)) { if(ord($msg[($i-1)])>127){ $han++; if($charset=="UTF-8"){ $i=$i+3; }else{ $i=$i+2; } }else{ $eng++; $i=$i+1; } if(($han+$eng)==$cut_size){ if($charset=="UTF-8"){ $cut_size = $eng + (int)$han*3; }else{ $cut_size = $eng + (int)$han*2; } break; } } for ($i=0;$i<$cut_size;$i++) { $str .=$msg[$i]; } return $str.$suffix; }[/code] [code]// 截取文字段落(超出长度用后缀表示) // 设计思路按照排除法,排除字符段落中的英文字符 // 再按照英文字符为1个占位符,中文为2个占位符(UTF-8的中文是3个占位符) // 计算出截取文字个数的占位符长度进行截取 function cut_str($msg,$cut_size,$charset="UTF-8",$suffix="...") { //验证截取个数,如果是0将不截取 if($cut_size<=0) return $msg; $i=1; $han=0; $eng=0; while ($i <= strlen($msg)) { //判断是否是ASCII扩展字符 if(ord($msg[($i-1)])>127){ $han++; if($charset=="UTF-8"){ $str .=$msg[($i-1)].$msg[($i)].$msg[($i+1)]; //如果是UTF-8跳过3个ASCII $i=$i+3; }else{ $str .=$msg[($i-1)].$msg[($i)]; $i=$i+2; } }else{ $eng++; $str .=$msg[($i-1)]; $i++; } //如果汉字和英文总和等于要截取的字符个数那么跳出循环 if(($han+$eng)==$cut_size){break;} } //如果汉字和英文总和等于要截取的字符个数那么不显示后缀 $suffix = ($han+$eng)<$cut_size?"":$suffix; return $str.$suffix; }[/code] September 29 在Smarty模板函数里面有这样一个方法:fetch("template.htm"),他和display("template.htm");最大的不同就是fetch()是把内容输出给一个变量,而display()是把内容输出给浏览器,这样我们就可以用一个变量来接收fetch()的输出,然后把他写入到文件中去. require_once(DIRROOT.'smarty/Smarty.class.php'); $smarty = new Smarty(); $smarty->template_dir = DIRROOT.'/smarty/template/'; $smarty->compile_dir = DIRROOT.'/smarty/tempcomp/'; $smarty->cache_dir = DIRROOT.'/smarty/caches/'; $smarty->cache_lifetime = 600 ; $smarty->left_delimiter = "{-"; $smarty->right_delimiter = "-}"; $smarty->caching = false; //$smarty->caching = true; $html=$smarty->fetch("template.htm"); $fp = fopen($file_name,"w+"); if(!fwrite($fp,$html)){ die('生成html文件失败!'); } fclose($fp); September 28 1. Opener:获取创建本窗口的窗口的引用,不在本窗口的对象层次体系中 只能在用window.open打开的页面中窗口中可以访问到opener属性,而对于用showModalDialog和showModalessDialog弹出的窗口则不能访问到,其opener属性引用为空。 2. parent,top:获取的是对本窗口中对象层次元素的引用,对于用iframe或者frame的较有实际意义 对于用window.open和showModalDialog以及showModalessDialog打开的窗口而言,返回的是本窗口对象层次的元素引用,对于这种情况,parent,top,self三者的引用相同,都是当前的窗体自身,但对于窗体中的 frame和iframe加载的页面元素来说,返回的则不相同。parent 返回的时包含该iframe的页面窗口引用,top则返回最上层的窗口引用,self当然返回的仍然是自身的引用。 3. self,window都是获取当前页面窗口自身对象的引用 每个页面自身代码中访问页面自身窗体可以采用self和window来访问到。 4. 利用window参数传递和dialogArguments来获取弹出窗口的窗口引用 为了能够在用showModalDialog和showModalessDialog弹出窗口中引用到弹出窗口的引用,我们可以在showModalDialog和showModalessDialog的第二个参数传入window,然后再弹出的页面中用 dialogArguments来获取刚才传入的window,即弹出窗口的窗口的引用。 使用JavaScript框架 在讲述 window 对象的时候,我们提到过,一个框架内的网页也是 window 对象,也就是说,Frame 对象也是 window 对象。用最容易理解的话说,每一个 HTML 文件占用一个 window 对象,包括定义框架的网页(“框架网页”)。在 IE 里用“<iframe>”标记在文档中插入的框架也是 window 对象,但是用“包含网页”的方法(在 HTML 中显示为“<!--webbot bot="include" ...-->”)读取的 HTML 就不占用独自的 window 对象。每一个框架都是包含它的页的 window 对象的一个子对象(不知道应该叫“属性”不该),要引用它,可以用以下几种方法之一: window.frames[x] window.frames['frameName'] window.frameName
其中,x 指的是该 window 对象中指定的第几个框架,与其它数组一样,x 也是从零开始的。frameName 指的是该框架的名字,跟<frame>里的“name”属性一样。 如果使用 window.frameName 指定的 window 对象又是一个框架网页,那么引用它的框架的方法:window.frameName.subFrameName。以此类推。 要注意的时,无论在何处,引用“window”对象所返回的,都是“当前”window 对象。如果要访问其它 window 对象,就要用到 parent 和 top 属性。parent 指的是“父级”window 对象,也就是包含当前 window 对象的框架网页;top 指的是窗口最顶端的 window 对象。 使用框架还要密切留意你的 JavaScript 中定义的全局变量和自定义函数。它们都有它们的所属——所在的 window 对象。要引用其它框架中的全局变量或自定义函数,都要用“窗口对象.框架对象[.框架对象…].全局变量或自定义函数”这种很烦的方法。 以上这个问题在建立连接时经常会被忽略:如果在<head>中定义了一个默认目标窗口(<base target="...">),在<a href="javascript:...">中,要知道输入的 JavaScript 语句是在默认目标窗口中运行的,必要时加一些“parent”“top”属性。 框架编程概述 一个HTML页面可以有一个或多个子框架,这些子框架以<iframe>来标记,用来显示一个独立的HTML页面。这里所讲的框架编程包括框架的自我控制以及框架之间的互相访问,例如从一个框架中引用另一个框架中的 JavaScript变量、调用其他框架内的函数、控制另一个框架中表单的行为等。 框架间的互相引用 一个页面中的所有框架以集合的形式作为window对象的属性提供,例如:window.frames就表示该页面内所有框架的集合,这和表单对象、链接对象、图片对象等是类似的,不同的是,这些集合是document的属性。因此,要引用一个子框架,可以使用如下语法: window.frames["frameName"]; window.frames.frameName window.frames[index]
其中,window字样也可以用self代替或省略,假设frameName为页面中第一个框架,则以下的写法是等价的: self.frames["frameName"] self.frames[0] frames[0] frameName
每个框架都对应一个HTML页面,所以这个框架也是一个独立的浏览器窗口,它具有窗口的所有性质,所谓对框架的引用也就是对window对象的引用。有了这个window对象,就可以很方便地对其中的页面进行操作,例如使用window.document对象向页面写入数据、使用 window.location属性来改变框架内的页面等。 下面分别介绍不同层次框架间的互相引用: 1.父框架到子框架的引用 知道了上述原理,从父框架引用子框架变的非常容易,即: window.frames["frameName"];
这样就引用了页面内名为frameName的子框架。如果要引用子框架内的子框架,根据引用的框架实际就是window对象的性质,可以这样实现: window.frames["frameName"].frames["frameName2"];
这样就引用到了二级子框架,以此类推,可以实现多层框架的引用。 2.子框架到父框架的引用 每个window对象都有一个parent属性,表示它的父框架。如果该框架已经是顶层框架,则window.parent还表示该框架本身。 3.兄弟框架间的引用 如果两个框架同为一个框架的子框架,它们称为兄弟框架,可以通过父框架来实现互相引用,例如一个页面包括2个子框架: <frameset rows="50%,50%"> <frame src="1.html" /> <frame src="2.html" /> </frameset>
在frame1中可以使用如下语句来引用frame2: self.parent.frames["frame2"];
4.不同层次框架间的互相引用 框架的层次是针对顶层框架而言的。当层次不同时,只要知道自己所在的层次以及另一个框架所在的层次和名字,利用框架引用的window对象性质,可以很容易地实现互相访问,例如: self.parent.frames["childName"].frames["targetFrameName"];
5.对顶层框架的引用 和parent属性类似,window对象还有一个top属性。它表示对顶层框架的引用,这可以用来判断一个框架自身是否为顶层框架,例如: //判断本框架是否为顶层框架 if(self==top){ //dosomething }
改变框架的载入页面 对框架的引用就是对window对象的引用,利用window对象的location属性,可以改变框架的导航,例如: window.frames[0].location="1.html";
这就将页面中第一个框架的页面重定向到1.html,利用这个性质,甚至可以使用一条链接来更新多个框架。 <frameset rows="50%,50%"> <frame src="1.html" /> <frame src="2.html" /> </frameset> <!--somecode--> <a href="frame1.location='3.html;frame2.location='4.html'" >link</a> <!--somecode-->
引用其他框架内的JavaScript变量和函数 在介绍引用其他框架内JavaScript变量和函数的技术之前,先来看以下代码: <script language="JavaScript" type="text/javascript"> <!-- function hello(){ alert("hello,ajax!"); } window.hello(); //--> </script>
如果运行了这段代码,会弹出“hello,ajax!”的窗口,这正是执行hello()函数的结果。那为什么hello()变成了window对象的方法呢?因为在一个页面内定义的所有全局变量和全局函数都是作为window对象的成员。例如: var a=1; alert(window.a);
就会弹出对话框显示为1。同样的原理,在不同框架之间共享变量和函数,就是要通过window对象来调用。 例如:一个商品浏览页面由两个子框架组成,左侧表示商品分类的链接;当用户单击分类链接时,右侧显示相应的商品列表;用户可以单击商品旁的【购买】链接将商品加入购物车。 在这个例子中,可以利用左侧导航页面来存储用户希望购买的商品,因为当用户单击导航链接时,变化的是另外一个页面,即商品展示页面,而导航页面本身是不变的,因此其中的JavaScript变量不会丢失,可以用来存储全局数据。其实现原理如下: 假设左侧页面为link.html,右侧页面为show.html,页面结构如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> New Document </title> </head> <frameset cols="20%,80%"> <frame src="link.html" /> <frame src="show.html" /> </frameset> </html>
在show.html中展示的商品旁边可以加入这样一条语句: <a href="void(0)" >加入购物车</a> 其中link表示导航框架,在link.html页面中定义了arrOrders数组来存储商品的id,函数addToOrders()用来响应商品旁边【购买】链接的单击事件,它接收的参数id表示商品的id,例子中是一个id为32068的商品: <script language="JavaScript" type="text/javascript"> <!-- var arrOrders=new Array(); function addToOrders(id){ arrOrders.push(id); } //--> </script>
这样,在结帐页面或是购物车浏览页面就可以用arrOrders来获取所有准备购买的商品。 框架可以使一个页面划分为功能独立的多个模块,每个模块之间彼此独立,但又可以通过window对象的引用来建立联系,是Web开发中的一个重要机制。在 Ajax开发中,还可以利用隐藏框架实现各种技巧,在后面介绍Ajax实例编程时可以发现,无刷新上传文件以及解决Ajax的前进后退问题都会用到这种技术。 通过iframe调用页面,然后在子级页面执行父级的函数 parent.window.[函数名称] September 24 用dedecms做了一个下载站 分享一下我在使用dedecms过程中的一些修改方法。希望对新手们有用 1.突破下载地址最多只能有9个的限制 修改 /dede/templets/soft_add.htm /dede/templets/soft_edit.htm 两个文件。 查找 Quote: if(endNum>9) endNum = 9; 将9替换为你想要的数量,不要太多哦 例如 Quote: if(endNum>25) endNum = 25; 然后修改 /dede/action/soft_add_action.php /dede/action/soft_edit_action.php 两个文件 查找 Quote: for($i=2;$i<=9;$i++) 将9替换为你要的数量[同上]。 2.软件模块加入快车联盟代码 修改 /plus/download.php 文件 查找 Quote: <?php 就是最顶上 在它上面增加 Quote: <script src="http://ufile.kuaiche.com/Flashget_union.php?fg_uid=你的快车联盟代码"></script> <?php require("Flashget_base64.php"); ?> 查找 Quote: else if($open==1){ $link = base64_decode($link); echo "<script language='javascript'>location=\"$link\";</script>"; exit(); 修改为 Quote: else if($open==1){ $link = base64_decode($link); $Url = ("你的网站url".$link); $flashgetUrl = FlashgetEncode($Url,联盟id); echo "<script>ConvertURL2FG('".$flashgetUrl."','".$Url."',联盟id);</script>"; exit(); 把后将快车联盟的 Flashget_base64.php 文件 放到 /plus/ 目录 登陆dedecms后台 系统设置 - 软件频道设置 把 附件下载方式 修改为 链接到跳转页面 3.软件模块加入迅雷联盟代码 跟快车的差不多 修改 /plus/download.php 文件 查找 Quote: <?php 在它上面加入 Quote: <script src="http://pstatic.xunlei.com/js/webThunderDetect.js"></script> 在它下面加入 Quote: require("encode.inc"); 查找 Quote: else if($open==1){ $link = base64_decode($link); echo "<script language='javascript'>location=\"$link\";</script>"; exit(); 替换为 Quote: else if($open==1){ $link = base64_decode($link); $Url = ("你的网站url".$link); $thunderUrl = ThunderEncode($Url); echo "<script>OnDownloadClick('".$thunderUrl."','',location.href,'你的联盟id',2,'')</script>"; exit(); } 把迅雷联盟的 encode.inc 文件 放到 plus 目录 登陆dedecms后台 系统设置 - 软件频道设置 把 附件下载方式 修改为 链接到跳转页面 September 15 date_format[格式化日期]| Parameter Position
| Type
| Required
| Default
| Description
|
| 1
| string
| No
| %b %e, %Y
| This is the format for the outputted date. 输出日期的格式。
|
| 2
| string
| No
| n/a
| This is the default date if the input is empty. 输入为空时的默认时间格式。 |
格式化从函数strftime()获得的时间和日期。
Unix或者mysql等的时间戳记(parsable by strtotime)都可以传递到smarty。
设计者可以使用date_format完全控制日期格式。
如果传给date_format的数据是空的,将使用第二个参数作为时间格式。
Example 5-8. date_format[日期格式]
index.php:
$smarty = new Smarty; $smarty->assign('yesterday', strtotime('-1 day')); $smarty->display('index.tpl');
index.tpl:
{$smarty.now|date_format} {$smarty.now|date_format:"%A, %B %e, %Y"} {$smarty.now|date_format:"%H:%M:%S"} {$yesterday|date_format} {$yesterday|date_format:"%A, %B %e, %Y"} {$yesterday|date_format:"%H:%M:%S"}
输出结果:
Feb 6, 2001 Tuesday, February 6, 2001 14:33:00 Feb 5, 2001 Monday, February 5, 2001 14:33:00
|
|
Example 5-9. date_format conversion specifiers[日期转换说明]
%a - abbreviated weekday name according to the current locale (根据当地格式输出“星期”缩写格式)
%A - full weekday name according to the current locale (根据当地格式输出“星期”全称格式)
%b - abbreviated month name according to the current locale (根据当地格式输出“月”缩写格式)
%B - full month name according to the current locale (根据当地格式输出“月”全称格式)
%c - preferred date and time representation for the current locale
%C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
%d - day of the month as a decimal number (range 00 to 31)
%D - same as %m/%d/%y
%e - day of the month as a decimal number, a single digit is preceded by a space (range 1 to 31)
%g - Week-based year within century [00,99]
%G - Week-based year, including the century [0000,9999]
%h - same as %b
%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
%j - day of the year as a decimal number (range 001 to 366)
%k - Hour (24-hour clock) single digits are preceded by a blank. (range 0 to 23)
%l - hour as a decimal number using a 12-hour clock, single digits preceeded by a space (range 1 to 12)
%m - month as a decimal number (range 01 to 12)
%M - minute as a decimal number
%n - newline character
%p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
%r - time in a.m. and p.m. notation
%R - time in 24 hour notation
%S - second as a decimal number
%t - tab character
%T - current time, equal to %H:%M:%S
%u - weekday as a decimal number [1,7], with 1 representing Monday
%U - week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week
%V - The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week.
%w - day of the week as a decimal, Sunday being 0
%W - week number of the current year as a decimal number, starting with the first Monday as the first day of the first week
%x - preferred date representation for the current locale without the time
%X - preferred time representation for the current locale without the date
%y - year as a decimal number without a century (range 00 to 99)
%Y - year as a decimal number including the century
%Z - time zone or name or abbreviation
%% - a literal `%' character
PROGRAMMERS NOTE: date_format is essentially a wrapper to PHP's strftime() function. You may have more or less conversion specifiers available depending on your system's strftime() function where PHP was compiled. Check your system's manpage for a full list of valid specifiers.
程序员提示:date_format本质上是php的strftime()函数的一个包装。 当php被编译的时候你可以或多或少的依靠系统的strftime()转换有效的区分符。 可以查看系统手册的有效区分符的全表.
|
|
September 07 在Slackware中,adduser
指令是個script程式,利用交談的方式取得輸入的用戶帳號資料,然後再交由真正建立帳號的useradd指令建立新用戶,如此可方便管理員建立用戶帳
號。在Red Hat Linux中,adduser指令則是useradd指令的符號連接,兩者實際上是同一個指令。 【adduser】 adduser 除了新增帳號外,還會自動新增 /home/XXX(家目錄) 並將 /etc/skel 複製預設的檔案至使用者家目錄。Enter 後得輸入密碼及相關資訊..等等,其中這些資訊當放在 /etc/passwd 裡。
# sudo adduser albert Adding user `albert' ... Adding new group `albert' (1005) ... Adding new user `albert' (1005) with group `albert' ... Creating home directory `/home/albert' ... Copying files from `/etc/skel' ... 輸入新的 UNIX 密碼: 再次輸入新的 UNIX 密碼: passwd:密碼已成功地變更 正在改變 albert 的使用者訊息 請輸入新值,或直接按 ENTER 鍵以使用預設值 全名 []: Albert3537 房間號碼 []: 201 工作電話 []: 07-7310606#49311106 家庭電話 []: Orz 其它 []: qq 以上的資訊都正確嗎?[y/N] y
要是想讓新增的使用者具有管理權限,則輸入
# adduser XXX admin Adding user XXX to group admin... Done.
可使用 grep 做確認。想刪除可用 deluser。 # grep admin /etc/group grep admin /etc/group lpadmin:x:108:albert admin:x:110:albert December 06
在我们的生活中,只要你睁开眼睛就能看到各种各样的视觉。不同的视觉能给你不同的视觉暗示,同样能给你不同的心理感受。视觉这个话题太泛了,大自然中无所不在,我们接下来主要谈谈在软件设计中视觉表达的准确性。
一、找对你的感觉。 视觉设计首先要考虑的就是整体的感觉,即视觉设计的风格。视觉设计的风格是否准确关系着设计的成败。一个大家闺秀你不能把她打扮的象个婊子,当然这是对人的感觉;那么一个产品的视觉设计也同样需要一个对的定位,最终以合适的视觉表现出来。我们不妨以几种聊天软件来做个的比较,从中窥视一点设计定位的视觉意味。看下面一组图:
 (从左至右为图一、图二、图三)
图一: QQ的视觉定位是以青少年为主的,所以它的视觉设计才采用了比较明亮活泼的色彩。 图二、图三:msn和TM的视觉定位是以办公室工作人员为定位,所以它的视觉使用比较稳定和平静的色彩。
令我感到失望的是,新版的TM2008给我的第一感觉象QQ,不知道这是否违背了原来的视觉定位?现在的TM2008让我感觉不如直接用QQ算了!我还是觉的原来TM更适合办公室使用,我不喜欢在办公室用QQ,所以我个人排斥了TM2008。TM2008如下图:
 ——图四 通过上面的图四我们可以看出,设计中竟然还有很多原本属于QQ的视觉元素,我个人不认为这是个成功的定位。
二、视觉结构和层级关系。 页面表现的层级关系和结构是用视觉的形式表现出来的,比如包含关系及业务的先后顺序的表现。让用户通过视觉就能够直接的明白应该先看什么,后看什么,元素时间是什么关系等等。就地取材,让我们来看下面的两张图:
 ——图五 wordpress博客的后台管理界面,我们可以看到清晰的从属关系:管理–>文章–>文章内的修改区域。
 ——图六 图六中,vista系统的界面:三个区域的层级关系一目了然 ,“1”区域要高出“2”区域,“2”区域要比“3”区域的颜色深,这样整体的从属关系就很明显:
 ——图七
当然我只是说明层级关系需要视觉表达,其中有很多的细节因素就不再次赘述了。
二、是什么就是什么,图形达意尽量明确。 视觉元素在软件中都代表着一定的含义,什么样子代表什么都有其特定的视觉暗示,如果不是游戏,我们应该尽量避免和用户捉迷藏。例如应该用页签来表现的从属关系,我们不应该简单的做几个链接,这样会表达不清楚各部分关系。除此类的布局因素之外,图标的表达是软件视觉中的一大块,好的图形表达可以帮助用户直观感受功能,缩短操作时间,提高效率;不过表达不好可就麻烦了,用户可能要歪着脑袋想半天!
 ——图八 在图八中,箭头所指之处为刷新图标,上面那个刷新图为原来图标,下面的刷新图标是我做个假设。对于一个新手,下面那张图的刷新图标和后退图标显得太象了,意思区别不是太明确,会造成误解。就准确性而言,上面那个刷新图标更让我容易接受。我承认我这样假设有点扣小节,我的本意是为了说明图形表达准确性。
三、明确你的视觉状态 在软件里,软件视觉的状态主要用来表现对用户的行为反馈,在计算机pc环境里的软件,主要针对鼠标和键盘操作,理想状态是:用户的每个操作行为都应该有相应的视觉反馈,比如有没有选中,操作有没有成功等。仅按鼠标操作的状态分就有默认、鼠标指向、鼠标按下、鼠标点击四种状态,准确的反馈可以让用户流畅的感觉自己的操作;关于鼠标和键盘的状态,大家在操作系统的时候注意一下,就可以看到各种操作的对应关系,而我们平时是不太注意的,因为它默默的达到了设计的目的。站在是否可用的角度分有:可用状态、不可用状态.
 ——图九,本图为两种不同状态的视觉比较,不可用状态的灰色让我不再去点击。 状态的准确性可以可以避免用户误用不可用的操作而产生麻烦和浪费时间,这种情况我们可以通过一个视觉反馈轨迹图来看看操作的情况。
 ——图十 图十是我在为一个产品做用户测试的时候,所得到的反馈图:在没有选择文件的时候,移动文件是不可用的,视觉处理的时候却是可以点击的,再加上视觉顺序的不合理,大多数的用户总是直接点击“移动文件”,犯下错误之后才去选择文件,途中的虚线部分表示犯错之后又才去选择文件,重新来过。
四、请用准确的视觉来辅助信息反馈 信息反馈一般有一下五种情况:成功、失败、询问、警告、错误\异常,我们用来对应的视觉辅助图要力求表现每种情况的准确含义,比如我见过有的软件用一个惊讶的表情来表示警告,但往往被误以为是询问或者出现了异常。一般的视觉表现如下图:
 ——图十一 图十一是我们在做gui设计时做的,基本按照通用的符号。
当然,为了增加趣味性,我们可以允许任意表现形式或表情的存在,前提是你的表达要准确,不要有歧义,否则使用者的第一反映可能不是你要表现的,由于理解的歧义所带来的损失和挫折感会让用户感到厌恶。通过搜索找到一些图,组合起来对比一下:
 ——图十二 图十二中的第一张是我搜索到的错误表现图,想必大家都见过,如果你犯错的时候出现了,你会想到什么?第三张图的淘气鬼脸图,我以为我成功了;第四张图的表现让我以为是在警告。只有第二张图让我意识到我失败了,并且有趣味性。可见趣味性和准确性并不矛盾,我们在设计趣味性的同时,别忽略设计的准确性。 November 19
核心理念就是以人为本,基础之一是计算的平台——多核、并行和移动计算,我们可以看到硬件和网络的发展趋势非常迅猛。另一个是快速的开发工具和动态语言的
发展,我们称为工具和语言的2.0。基于这两个基础,产生了两个方向的变革。一是新一代Web开发,随着Web
2.0概念的深入,新一代互联网模型己初步形成。另一个方向是Enterprise
2.0,包括SaaS软件服务。这两个方向,对于整个软件的未来发展,都有着深远的影响。历史上,很多公司因为抢占技术变革的高地,获得市场先机,同时也
有不少公司,因为没有跟上技术发展的趋势而消失消亡。我们希望通过这样的大会,把正在发展的变化、正在发展的趋势,让中国更多的技术人员更加深入地了解,
跟上新一代软件开发浪潮,这是很有意义的。
|