cygwin的坑坑洼洼

背景介绍

使用中遇到的问题

cygwin使用过程当中存在不少问题,例如权限、时区之类的问题。html

本文目的

弄清楚cygwin的哪些操做或者特性会跟windows自己的冲突,以便更好的使用cygwin管理Windows Server系统。node

环境

操做系统:WindowsServer2012 x64linux

Cygwin版本: CYGWIN_NT-6.2 TEST 2.0.2(0.287/5/3)2015-05-0817:00 x86_64 Cygwinshell

Cygwin核心概念

Windows安全概述

Windows NT系统包含了一个基于ACL的复杂的安全模型,cygwin默认状况下在支持它们的文件系统(一般会是NTFS)上将Win32文件的属主和权限映射为ACL。拥有Administrator权限的用户能够修改文件的属主。数据库

在Windows安全模型中,几乎全部的object都是安全的。这里的object指的是文件、进程、线程、信号量等。每个object都有一个叫作SD(security descriptor)的数据结构,SD包含了全部的权限管理信息。vim

SD包含下面几个要素:windows

  • Flags which control several aspects of this SD. This is not discussed here.安全

  • object属主的SIDbash

  • 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;

  • 第三、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个文件测试一下权限,效果分别以下图所示: 
150605170455

左图为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

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命令行工具

全部cygwin的命令行工具都支持 –help(-h)/–version 参数来获取帮助和查询版本。

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)

HOME主目录

若是某些其余软件(如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.

inode

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

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路径

是能够的,可是不推荐这样用。

下面路径会被认为是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系统中,文件名是不区分大小写的。

.exe扩展名

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文件。

@pathname

在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特性有很大不一样,下面列出一些须要注意的地方:

  1. cygwin仅仅是对windows系统的文件系统作了一下POSIX映射,自己并不提供文件系统的驱动;

  2. 一些windows自带的命令行工具(例如:find.exe,link.exe,sort.exe等),可能会与cygwin冲突,要确保这些命令使用了绝对路径(/usr/bin/find),或者在PATH环境变量中要将cygwin的bin目录放在前面;

  3. windows系统没法识别cygwin的文件路径格式,因此须要借助cygpath命令进行转换,例如:notepad.exe “$(cygpath -aw “Desktop/Phone Numbers.txt”)”;

  4. 一些cygpath的工具,例如:ncftp/lynx/wget等,须要网络链接,而且cygpath是依赖于windows的网络链接的,因此若是这些工具出现问题,须要使用windows的工具(ping.exe/telnet/ftp)进行调试;

  5. cygpath和windows的符号连接是不同的;

  6. 编码格式;

  7. 用户、组,文件权限、ACL等安全特性的区别;

问题汇总

cygwin安装sshd

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 中也有说明)。

关键的就是这两个用户都要建立。

解决Cygwin下vi和vim方向键和Backspace很差用的问题

默认的vi(vim)没有配置文件,所以致使了方向键出现ABCD,以及Backspace只会移动光标,字符不消失的问题。cygwin自带vi(vim)配置文件的例子,直接拷贝便可,参考如下命令:

$ cp /usr/share/vim/vim74/vimrc_example.vim  ~/.vimrc
Cygwin 中 “Command not found” 的问题

在 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。

cgywin命令输出有中文乱码

执行一些命令(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

Cywin输入、显示中文不正常

解决:修改.inputrc,解除如下几行注释:

#set meta-flag on #set convert-meta off#set input-meta on#set output-meta on

命令行下面home/end键无效

在~/.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

相关文章
相关标签/搜索