cygwin使用过程中存在很多问题,例如权限、时区之类的问题。
弄清楚cygwin的哪些操作或者特性会跟windows本身的冲突,以便更好的使用cygwin管理Windows Server系统。
操作系统:WindowsServer2012 x64
Cygwin版本: CYGWIN_NT-6.2 TEST 2.0.2(0.287/5/3)2015-05-0817:00 x86_64 Cygwin
Windows NT系统包含了一个基于ACL的复杂的安全模型,cygwin默认情况下在支持它们的文件系统(通常会是NTFS)上将Win32文件的属主和权限映射为ACL。拥有Administrator权限的用户可以修改文件的属主。
在Windows安全模型中,几乎所有的object都是安全的。这里的object指的是文件、进程、线程、信号量等。每一个object都有一个叫做SD(security descriptor)的数据结构,SD包含了所有的权限管理信息。
SD包含下面几个要素:
Flags which control several aspects of this SD. This is not discussed here.
object属主的SID
object属组的SID
一个ACE(Access Control Entries)列表,称为DACL(Discretionary Access Control List)
另外一个ACE列表,称为SACL(Security Access Control List)
每个ACE都包含一个SID(Security IDentifier)。SID是所有用户、组、计算机、AD域的唯一标识符。与POSIX中的UID/GID不同的是,SID是跨计算机、域全局唯一的。
例如:一个计算机“foo”的SID为:
S-1-5-21-165875785-1005667432-441284377
该计算机“foo”中的一个用户“johndoe”的SID为:
S-1-5-21-165875785-1005667432-441284377-1023
格式:
第1段恒为S;第2段为SID结构的版本号,目前为1;
第3、4段代表SID的类型或类别,计算机和域永远以S-1-5-21开始;
接下来的3段是一个32位的值,代表一个计算机系统的96位唯一标识;
用户的SID是在计算机SID的后面加上一个编号,这个编号称为RID(relative identifier),当用户创建的时候,RID就跟着一起创建出来了。
对域而言,也是类似的结构。
SID of a domain “bar.local”:
S-1-5-21-186985262-1144665072-740312968
SID of a user “johndoe” in the domain “bar.local”:
S-1-5-21-186985262-1144665072-740312968-1207
注意:虽然上面的johndoe用户在计算机中存在,又在域中存在,但是他具有不同的SID,因此这两个SID并不是同一个账户。不同的SID,就是不同的账户。
从Cygwin 1.7.34版本之后,cygwin就会自动的将Windows中的SID翻译成POSIX的UID、GID。Windows系统中的RID会被转换成/etc/passwd、/etc/group中的UID、GID。
ACE包含3个部分:
ACE类型:allow ACE或deny ACE
32位的权限位
这些权限允许或拒绝的SID
cygwin将Windows系统的文件权限实现成POSIX的文件权限,而POSIX文件是以ACL来管理文件权限的。POSIX的文件、目录权限是被mount选项来控制的,默认设置为acl。
也就是说在默认情况下,/etc/fstab文件内容为:
none /cygdrive cygdrive binary,posix=0,user 00
这说明cygwin会模拟POSIX文件权限,从而可能会导致Windows系统中应用程序的文件权限产生混乱,为了解决这个问题,需要添加noacl参数,将/etc/fatab改为:
none /cygdrive cygdrive binary,user,noacl,posix=000
在D:\(即/cygwin/d)下分别创建3个文件测试一下权限,效果分别如下图所示:
左图为Windows系统中创建的文件的权限,中间为cygwin在默认情况下模拟POSIX文件权限创建出来的文件权限,右图为cygwin添加了noacl参数之后,在cygwin中创建的文件的权限。可以看出,添加noacl参数之后,cygwin将不会模拟POSIX文件权限,在cygwin中创建的文件的权限跟Windows系统的文件权限保持一致。
但是上面的改动仅仅是修改了/cygdrive目录,也就是windows系统中的所有的磁盘(C:、D:、E:、F:等),而cygwin本身的/并未修改,同样会存在上述的权限问题,因此需要一并修改,最终完整的/etc/fatab文件内容如下:
none /cygdrive cygdrive binary,user,noacl,posix=000 D:\cygwin64 / ntfs binary,noacl,override00 D:\cygwin64\bin/usr/bin ntfs binary,noacl,override00 D:\cygwin64\lib /usr/lib ntfs binary,noacl,override00
cygserver 是为Cygwin作为后台服务运行而设计的,默认安装Cygwin的时候并没有启动它。我们需要打开它,并将它作为Windows的标准服务来安装。
在Cygwin中输入命令:
cygserver-config
按照界面提示进行cygserver的安装,并同意将其安装为服务。
运行该服务:
cygrunsrv --start cygserver
cygrunsrv其实是启动的Windows标准服务cygserver,这个命令也可以在Cmd下这样做: net start cygserver,或者也可以按下按键 Windows+R ,键入 services.msc 回车,找到CYGWI cygwerver服务,并启动之。
查看cygserver服务的状态:
cygrunsrv --qurey cygserver
cygserver的配置文件:
/etc/cygserver.conf
所有cygwin的命令行工具都支持 �Chelp(-h)/�Cversion 参数来获取帮助和查询版本。
cygcheck:列出系统信息,检查已安装的包,查询包的数据库。 cygpath:对windows和unix文件路径做转换。例如,对于文件“~/.bashrc”-w转换为windows文件路径“D:\cygwin64\home\yhn1792\.bashrc”,-u转换为unix文件路径“/home/yhn1792/.bashrc”。 dumper:对windows进程进行core dump,便于进行gdb调试。 getconf:将系统配置变量值写入标准输出。 getfacl:获取文件或目录的ACL。 setfacl:设置文件或目录的ACL。 kill:给cygwin进程发送信号。 ldd:显示共享的lib依赖关系。 locale:获取locale信息。 mkgroup:显示/etc/group风格的组。 mkpasswd:显示/etc/passwd风格的用户。 mount:显示挂载点,或挂载文件系统。 umount:卸载文件系统。 passwd:修改用户的密码或者密码的属性。 pldd:显示一个进程加载的动态共享对象。 ps:显示cygwin进程的状态。-W参数可以列出windows系统的进程。 regtool:查看或者修改windows系统的注册表。 strace:跟踪系统调用和信号。 tzset:从当前的windows系统时区设置中打印POSIX兼容的时区ID。export TZ=$(tzset)
如果某些其他软件(如msysGit)为 Windows 设置了 HOME 环境变量,会影响到 Cygwin 中用户主目录的设置,甚至会造成在 Cygwin 中不同的命令有不同的用户主目录的情况。例如:Cygwin下Git 的用户主目录被设置为 /cygdrive/c/Documents and Settings/jiangxin,而 SSH 客户端软件的主目录被设置为 /home/jiangxin,这会给用户造成困惑。
之所以出现这种情况,是因为 Cygwin 确定用户主目录有几个不同的依据,要按照顺序确定主目录:
首先查看系统的 HOME 环境变量;
其次查看 /etc/passwd 中为用户设置的主目录。
有的软件遵照这个原则,而有些 Cygwin 应用如 SSH,却没有使用 HOME 环境变量而是直接使用 /etc/passwd 中的设置。要想避免在同一个 Cygwin 环境下有两个不同的用户主目录设置,可以采用下面两种方法。
方法1:修改 Cygwin 启动的批处理文件(如:C:\cygwin\Cygwin.bat ),在批处理的开头添加如下的一行代码,就可以防止其他软件在 Windows 引入的 HOME 环境变量被带入到 Cygwin 中。
set HOME=
方法2:如果希望使用 HOME 环境变量指向的主目录,则可通过手工编辑 /etc/passwd 文件,将其中的用户主目录修改成 HOME 环境变量所指向的目录。
Windows 的文件系统忽略文件名的大小写,在 Cygwin 下最好对命令行补齐进行相关设置,以忽略大小写,这样使用起来更方便。
编辑文件 ~/.inputrc ,在其中添加设置:
set completion-ignore-case on
或者取消已有的相关设置前面的井(#)号注释符。
修改完毕后,再重新进入 Cygwin,这样就可以实现命令行补齐对文件名大小写的忽略。
查看时区命令:
tzset
查看时区环境变量:
echo $TZ
查看系统当前时间(UTC时间):
cygcheck -s | grep -i time
查看当前时间(GMT时间):
date -R
下面,通过一个样例来演示如何设置时区:
### 查看当前UTC时间 $ cygcheck -s | grep -i time CurrentSystemTime:FriJun0507:50:252015### 查看当前GMT时间,UTC+8小时 $ date -R Fri,05Jun201515:50:44+0800### 设置为洛杉矶时间进行测试(注意:此时仅在当前shell环境生效,如需全局生效请写入配置文件) $ export TZ=America/Los_Angeles### UTC时间不变 $ cygcheck -s | grep -i time CurrentSystemTime:FriJun0508:50:502015### 当前时间变为洛杉矶当地时间,UTC-7 $ date -R Fri,05Jun201500:50:56-0700
cygwin支持POSIX以及Win32类型的文件路径格式,使用/或者\来分割文件路径。cygwin的DLL库会根据需要将POSIX格式转换为native NT格式。
$ df -h 文件系统容量已用可用已用%挂载点 D:/cygwin64/bin 16G661M15G5%/usr/bin D:/cygwin64/lib 16G661M15G5%/usr/lib D:/cygwin64 16G 661M 15G 5% / C:45G18G27G41%/cygdrive/c D:16G661M15G5%/cygdrive/d E:3.6G3.6G0100%/cygdrive/e
从cygwin1.7.0版本之后,Windows文件系统的POSIX样式布局将会保存在/etc/fatab文件中,这是一个全局文件,每个用户的文件可以保存在/etc/fstab.d/${USER}。
$ cat /etc/fatab none /cygdrive cygdrive binary,posix=0,user 00
cygwin用以下几种方式创建符号链接:
默认以纯文本格式创建,指明了目标文件的路径,标记为DOS SYSTEM属性,使用UTF-16编码目标文件的文件名;
Windows的快捷方式格式.lnk,有一个特殊的header和DOS READONLY属性,当CYGWIN环境变量设置为winsymlinks 或winsymlinks:lnk的时候将会创建这种类型的符号链接;
Native Windows symlinks:Windows Vista/2008或更新版本,当CYGWIN环境变量设置为winsymlinks:native or winsymlinks: nativestrict的时候将会创建这种类型的符号链接;
在NFS文件系统上,cygwin会创建真正的NFS符号链接;
注意:上述的各种符号链接能在所有环境下识别和使用,但是如果纯文本符号链接丢失了DOS SYSTEM属性、快捷方式格式的符号链接丢失了DOS READONLY属性,那它们将不会被认为是一个符号链接。
Hard links are fully supported on NTFS and NFS file systems. On FAT and other file systems which don’t support hardlinks, the call returns with an error, just like on other POSIX systems.
On file systems which don’t support unique persistent file IDs (FAT, older Samba shares) the inode number for a file is calculated by hashing its full Win32 path. The inode number generated by the stat call always matches the one returned in d_ino of the dirent structure. It is worth noting that the number produced by this method is not guaranteed to be unique. However, we have not found this to be a significant problem because of the low probability of generating a duplicate inode number.
$ ls -lai /tmp/总用量23281474976710864 drwxrwxrwt+1AdministratorNone06月114:30.281474976710851 drwxr-xr-x+1AdministratorNone06月119:07..844424930152905-rw-r--r--1AdministratorNone776月114:29 awk.1040844424930152887-rw-r--r--1AdministratorNone776月114:29 awk.1668844424930150273-rw-r--r--1AdministratorNone776月114:22 awk.1716
Cygwin 1.7 and later supports Extended Attributes (EAs) via the linux-specific function calls getxattr, setxattr, list xattr, and removexattr. All EAs on Samba or NTFS are treated as user EAs, so, if the name of an EA is “foo” from the Windows perspective, it’s transformed into “user.foo” within Cygwin. This allows Linux-compatible EA operations and keeps tools like attr, or setfattr happy.
chroot从cygwin1.1.3开始支持,但是chroot并不是Windows上的概念。
在cygwin上chroot有很多限制:
a)chroot不是一个提升权限的命令,所有用户都可以调用它;
b)对本地Windows进程而言,chroot环境并不安全。
所以,在cygwin环境下不建议使用chroot。
Windows本地应用创建的文件是可以与cygwin应用共同协作的。例如,Windows本地应用创建的文件,应该是可以被cygwin应用可读的,反之亦然。
但是在文本文件中,Win32和UNIX是有不同的行结束符的。UNIX文本文件中行结束符是一个换行(Line Feed,LF),而Win32文本文件中是两个字符:一个回车符(Carriage Return,CR)和一个换行(Line Feed,LF)。
Unix/Binary:如果选择这一项,Cygwin不会转换文本文件中的行结束符。这是默认选项,适用于大多数的用户。选择该选项意味着,用标准的Windows工具(如Notepad)创建的文件,在用Cygwin环境下编译的程序(如cat)来查看时,貌似带有额外的行结束符。
DOS/Text:在这种模式下,Cygwin试图转换文件的行结束符,这样一来,用标准的Windows编辑器创建的文件和程序就好像是在Cygwin下运行的程序,因为每个行结束符只有一个LF字符。Cygwin不会为以二进制方式打开的文件执行该转换。(回想一下,在打开文件时需要传递一个标志,表明文件是文本还是二进制数据。)除非需要在环境中使用开发宿主机上的某些”顽固”的程序,否则不应该选择该选项。
cygwin的fork系统调用没有与Win32的API映射的很好,这导致很难正确的实现fork调用。当前,cygwin fork并不是copy-on-write机制。
在cygwin中,父进程创建子进程的流程:
父进程为子进程在cygwin进程表上初始化一个空间;
使用Win32的CreateProcess调用创建一个挂起的子进程;
父进程调用setjmp来保存他自己的上下文,并在cygwin共享内存中设置一个指向该上下文的指针;
父进程拷贝自己地址空间的数据到这个挂起的子进程的地址空间,来填充子进程的.data和.bss;
当子进程的地址空间初始化完成之后,子进程开始进入运行状态,父进程等待互斥量;
子进程发现自己已经被fork出来,然后使用以保存的调转buffer进行跳转。然后子进程设置父进程等待的互斥量,并且被另外一个互斥量阻塞;
父进程将堆栈数据拷贝到子进程,之后父进程释放子进程等待的互斥量,并且从fork调用中返回;
最后,子进程从最后一个互斥量中激活,重新创建从共享区域中传来的内存映射区域,然后从fork中返回;
总之,当前Windows的实现机制使得cygwin不可能实现一个完美、可靠的fork调用,偶尔的fork失败也是不可避免的。
根据POSIX标准,cygwin可以通过设置LC_ALL, LC_CTYPE, and LANG环境变量来改变语言,这三个变量是按顺序的。变量的内容依从于POSIX标准。
格式为:
language[[_TERRITORY][.charset][@modifier]]
“language”是一个ISO 639-1定义的两位、小写的语言代码字符串,如果没有语言在ISO 639-1中没有找到,则可以使用ISO 639-3的三位字符串来表示。
“TERRITORY”是ISO 3166中定义的两位大写国家码字符串。
“charset”为字符编码。
例如:
"fr_FR.UTF-8" language = french, territory =France, charset = UTF-8
注意:默认的locale是”C.UTF-8”。
Windows系统使用UTF-16对文件名进行编码,所以cygwin将根据LC_ALL, LC_CTYPE, and LANG变量来决定如何将UTF-16格式的文件名转换为cygwin指定的格式。
使用 locale.exe -a 命令查看所有locale列表。
潜在的问题
1. 一个cygwin进程启动的时候,Windows的环境变量由UTF-16转换为UTF-8,如果环境变量仅仅包含ASCII编码,那么就不会有问题。但是如果包含本地字符集,例如GBK,那么将可能会出现乱码的情况。
2. 符号链接:符号链接包含了目标文件的路径名,如果该路径名包含了非ASCII码,那么改变了locale之后,则有可能出现乱码。cygwin1.7以及之后的版本不存在该问题。
是可以的,但是不推荐这样用。
下面路径会被认为是native Win32路径:
a)以盘符开始的路径:
C:\foo C:/foo
b)全路径中至少包含了一个反斜杠:
C:/foo/bar\baz/...
c)UNC路径使用了反斜杠:
\\server\share\...
FAT或FAT32
a)读权限:在FAT或FAT32文件系统中,文件总是可读的; b)写权限:chmod只能改变文件的写权限; c)可执行权限:UNIX系统中文件是否有可执行权限取决于文件是否有x权限位,Windows系统中则是根据文件扩展名是否为.bat/.com/.exe/文件内容是否以#!开始等来判断。
NTFS
文件权限通过文件的ACL来确定
NFS
文件权限就是标准的POSIX权限了,从server端通过NFSv3协议传输过来。
/etc下面特殊的文件需要确保有PublicRead权限:
/etc/fstab /etc/fstab.d/$USER /etc/passwd /etc/group
Win32应用程序会认为包含AUX, COM1, LPT1 or PRN的文件名为非法的,例如:prn.txt or foo.aux等。但是这个限制对cygwin应用程序是无效的,cygwin应用不会认为它们是非法的。
在Windows文件系统中,ASCII码的1-31号字符不能用于文件名中,并且下面的字符在Win32 API中有着特殊的意义:
"*:<>?| \
cygwin将会把上面除了\之外的字符做一个转换,转换成UNICODE,范围是:0xf000 - 0xf0ff。因为\在文件路径中可以作为分隔符,所以不会对其进行转换。
Windows文件系统使用UTF-16的Unicode编码来存储文件名信息。如果不用UTF-8编码的话,那么很有可能会有一个或多个字符无法对应到你的字符集。
建议使用UTF-8字符集。
在Win32系统中,文件名是不区分大小写的。
Windows系统中,Win32可执行文件如果以.exe为扩展名,那么在执行命令的时候不需要带上.exe就可以执行了。但是如果是以.bat/.com为扩展名的文件则必须要带上其扩展名才可以执行。
例如:如果filename.exe存在,而filename不存在,那么ls filename将会列出filename.exe文件的信息。
如果一个shell脚本myprog和一个程序myprog.exe同时存在一个目录下,那么无.exe扩展的shell脚本myprog将会优先执行。即:./myprog将会执行shell脚本而不是myprog.exe,如果不存在myprog脚本,才会是去执行.exe文件。
在bash和cmd中使用@pathname会产生不同的效果,样例如下:
Example3.2Using@pathname bash$ /bin/echo ’Thisis"a long" line’> mylist bash$ /bin/echo @mylist@mylist bash$ cmd c:\> c:\cygwin\bin\echo @mylistThisis a long line
cygwin不是一个完整的操作系统,与windows的native特性有很大不同,下面列出一些需要注意的地方:
cygwin仅仅是对windows系统的文件系统做了一下POSIX映射,本身并不提供文件系统的驱动;
一些windows自带的命令行工具(例如:find.exe,link.exe,sort.exe等),可能会与cygwin冲突,要确保这些命令使用了绝对路径(/usr/bin/find),或者在PATH环境变量中要将cygwin的bin目录放在前面;
windows系统无法识别cygwin的文件路径格式,所以需要借助cygpath命令进行转换,例如:notepad.exe “$(cygpath -aw “Desktop/Phone Numbers.txt”)”;
一些cygpath的工具,例如:ncftp/lynx/wget等,需要网络连接,并且cygpath是依赖于windows的网络连接的,所以如果这些工具出现问题,需要使用windows的工具(ping.exe/telnet/ftp)进行调试;
cygpath和windows的符号链接是不一样的;
编码格式;
用户、组,文件权限、ACL等安全特性的区别;
cygwin安装成功后,连接 ssh localhost,一直出现错误:
cygwin Connection closed by::1
费了很多时间查找,总算解决了,原文如下:
在google上看到cygwin的一个官方mail问答。参考Installing the Cygwin SSH daemon 。问题关键就是一个特殊的权限问题,在SYSTEM账户下运行的sshd服务需要有改变user id的特权(关于权限的问题,在cygwin的/usr/share/doc/Cygwin/openssh.README 中已经说得很明确了:2003Server has a funny new feature.When starting services under SYSTEM account, these services have nearly all user rights which SYSTEM holds...exceptfor the "Create a token object" right, which is needed to allow public key authentication :-()。所以事件日志会有seteuid的错误。至于解决方案,就是让cygwin帮你创建两个特殊用户sshd和cyg_server,其中sshd服务在cyg_server用户下运行,cyg_server有相应的权限(在/usr/share/doc/Cygwin/openssh.README 中也有说明)。
关键的就是这两个用户都要创建。
默认的vi(vim)没有配置文件,因此导致了方向键出现ABCD,以及Backspace只会移动光标,字符不消失的问题。cygwin自带vi(vim)配置文件的例子,直接拷贝即可,参考以下命令:
$ cp /usr/share/vim/vim74/vimrc_example.vim ~/.vimrc
在 Cygwin 上面编译一些 Unix 软件时,比如 ffmpeg, gvim 等,由于 Unix / DOS 系统的差异经常会出现一些莫名奇妙的问题,最近经常碰到的一个问题就是:
line 9: $'\r': command not found
这样的错误,初步判断可能是因为 \r\n 的区别引起的,遇到这种情况,可以使用 dos2unix 来修复。
执行: dos2unix configure configure,之后再运行: ./configure ,就不会再出现上面的错误了。
windows中的换行符是\r\n, linux/unix下的换行符是\n。
其中:
回车符:\r=0x0d(13)return;#回车(carriage return) 换行符:\n=0x0a(10) newline。#换行(newline)在DOS使用的换行符为^M$,我们称为CR与LF两个符号。而在Linux中,则仅有LF ($)这个换行符。可以用如下命令完成格式转换:$dos2unix,$unix2dos。
执行一些命令(ipconfig等)如果有中文输出,则会出现中文乱码问题。
需要在Options->Text中将本地语言改为zh_CN,字符集改为GBK。
ls颜色:Cygwin默认ls的输出是没有颜色的,而Ubuntu等一些主流发行版默认为终端配置了颜色输出,由于Cygwin采用的mintty.exe虚拟终端是支持颜色的,因此可以编辑~/.bashrc文件,追加:
[plain] view plaincopy [-x /usr/bin/dircolors ]&&eval"$(dircolors -b)"alias ls='ls --color=auto'
grep颜色:同样,grep默认也没有颜色。编辑~/.bashrc文件,追加:
[plain] view plaincopy alias grep='grep --color=auto'
vim注释深蓝色问题:vim的默认语法着色中,注释是深蓝色,这在黑色背景下看不清楚。可以将其改成浅蓝色,编辑~/.vimrc(没有则创建),添加:
[plain] view plaincopy syntax on hi comment ctermfg=blue
或者将背景色设置为dark,编辑~/.vimrc文件,添加:
[plain] view plaincopy syntax on set background=dark
解决:修改.inputrc,解除以下几行注释:
#set meta-flag on #set convert-meta off#set input-meta on#set output-meta on
在~/.inputrc中添加如下几行:
vim ~/.inputrc "\e[3~":delete-char"\e[1~": beginning-of-line "\e[4~":end-of-line "\e[H": beginning-of-line "\e[F":end-of-line "\e[7~": beginning-of-line "\e[8~":end-of-line "\eOH": beginning-of-line "\eOF":end-of-line
cygwin用户手册:https://cygwin.com/cygwin-ug-net.html
cygwin安装指南:https://cygwin.com/install.html
cygwin FAQ:https://cygwin.com/faq.html
本文出自 “烟花易冷” 博客,转载请与作者联系!