chmod

(PHP 4, PHP 5, PHP 7, PHP 8)

chmod更改文件模式

描述

chmod(string $filename, int $permissions): bool

尝试将指定文件的模式更改为 permissions 中给定的模式。

参数

filename

文件路径。

permissions

请注意,permissions 不自动被假定为八进制值,因此,为了确保预期的操作,您需要在 permissions 前面加上一个零 (0)。诸如 "g+w" 之类的字符串将无法正常工作。

<?php
chmod
("/somedir/somefile", 755); // 十进制;可能不正确
chmod("/somedir/somefile", "u+rwx,go+rx"); // 字符串;不正确
chmod("/somedir/somefile", 0755); // 八进制;模式的正确值
?>

permissions 参数包含三个八进制数字组件,分别指定了所有者、所有者所在的组以及其他所有人的访问限制,顺序依次为所有者、所有者所在的组以及其他所有人。可以通过将所需权限加起来来计算一个组件。数字 1 表示授予执行权限,数字 2 表示使文件可写,数字 4 表示使文件可读。将这些数字加起来以指定所需的权限。您还可以使用 'man 1 chmod' 和 'man 2 chmod' 在 Unix 系统上阅读有关模式的更多信息。

<?php
// 所有者可读可写,其他人无权限
chmod("/somedir/somefile", 0600);

// 所有者可读可写,其他人可读
chmod("/somedir/somefile", 0644);

// 所有者拥有全部权限,其他人可读可执行
chmod("/somedir/somefile", 0755);

// 所有者拥有全部权限,所有者组可读可执行
chmod("/somedir/somefile", 0750);
?>

返回值

成功时返回 true,失败时返回 false

错误/异常

失败时,将发出 E_WARNING

注意

注意:

当前用户是 PHP 运行的用户。它可能与您用于正常 shell 或 FTP 访问的用户不同。在大多数系统中,只有拥有该文件的文件所有者才能更改其模式。

注意: 此函数不适用于 远程文件,因为要检查的文件必须通过服务器的文件系统访问。

参见

添加笔记

用户贡献的笔记 17 个笔记

57
MethodicalFool
13 年前
注意,注释中的几个示例建议执行类似以下操作

chmod(file_or_dir_name, intval($mode, 8));

但是,如果 $mode 是一个整数,那么 intval( ) 不会修改它。因此,这段代码...

$mode = 644;
chmod('/tmp/test', intval($mode, 8));

...会生成如下权限

1--w----r-T

相反,请使用 octdec( ),例如

chmod(file_or_dir_name, octdec($mode));

另见:https://php.net/manual/en/function.octdec.php
37
Geoff W
14 年前
注意使用引号包围第二个参数...

如果您使用引号,例如

chmod (file, "0644");

php 不会报错,但在运行 chmod 之前会进行隐式转换为 int。不幸的是,隐式转换没有考虑到八进制字符串,因此您最终会得到 644 的整数版本,即 1204 八进制
35
masha at mail dot ru
19 年前
有用的参考

值 权限级别
400 所有者可读
200 所有者可写
100 所有者可执行
40 组可读
20 组可写
10 组可执行
4 全局可读
2 全局可写
1 全局可执行

(摘自 http://www.onlamp.com/pub/a/php/2003/02/06/php_foundations.html)
17
pmichaud at pobox dot com
21 年前
在之前的帖子中,stickybit avenger 写道
一个小提示。我曾经被建议设置“粘滞位”,即使用 1777 作为 chmod 值...

注意,为了在文件中设置粘滞位,必须使用 '01777' (八进制) 而不是 '1777' (十进制) 作为 chmod 的参数

<?php
chmod
("file",01777); // 正确
chmod("file",1777); // 不正确,与 chmod("file",01023) 相同,导致没有所有者权限!
?>

经验法则:始终在八进制模式值前面加上一个零。
7
alex at feidesign dot com
19 年前
如果您由于 safe_mode 限制而无法使用 PHP 修改文件/目录的权限,但可以使用 FTP 修改它们的权限,只需使用 PHP 的 FTP 函数(例如 ftp_chmod 或 ftp_site)即可。效率不如直接修改,但可以正常工作。
9
paul maybe at squirrel mail org
16 年前
注意,info at rvgate dot nl 的 chmodnum 函数会产生错误的结果。结果是基数为 10 的数字,它们看起来像八进制数字。该函数还会忽略 setuid、setgid 和粘滞位,并且如果遇到这样的文件,则会产生错误的数字。相反,这段暴力代码可以正常工作。也许还有更简洁的方法,但这段代码的 CPU 占用率并不高(注意,它假设您已经检查了字符串是否确实有 10 个字符!)

<?php
$permissions
= 'drwxr-xr-x'; // 或其他
$mode = 0;

if (
$permissions[1] == 'r') $mode += 0400;
if (
$permissions[2] == 'w') $mode += 0200;
if (
$permissions[3] == 'x') $mode += 0100;
else if (
$permissions[3] == 's') $mode += 04100;
else if (
$permissions[3] == 'S') $mode += 04000;

if (
$permissions[4] == 'r') $mode += 040;
if (
$permissions[5] == 'w') $mode += 020;
if (
$permissions[6] == 'x') $mode += 010;
else if (
$permissions[6] == 's') $mode += 02010;
else if (
$permissions[6] == 'S') $mode += 02000;

if (
$permissions[7] == 'r') $mode += 04;
if (
$permissions[8] == 'w') $mode += 02;
if (
$permissions[9] == 'x') $mode += 01;
else if (
$permissions[9] == 't') $mode += 01001;
else if (
$permissions[9] == 'T') $mode += 01000;

printf('Mode is %d decimal and %o octal', $mode, $mode);
?>
3
Tuckbros
4 年前
使用 octdec 更新解决方案。 您必须将字符串作为参数传递给 octdec。

$mode = '644';
chmod(file_or_dir_name, octdec($mode));

另见:https://php.net/manual/en/function.octdec.php
6
chris at ocproducts dot com
4 年前
Windows 的文件权限模型与 Unix 非常不同,而且 Windows 对其整合程度有限。

在 Windows 上,此函数只能更改“只读”标志,该标志在 $mode & 0200 未通过时打开。
即它只检查 u+w 是否缺失于位掩码中,如果缺失,则设置只读标志。

不能设置可执行标志,因为 Windows 基于文件扩展名来确定它。
不能设置写入标志,因为 Windows 基于 ACL 确定写入访问权限,而 ACL 在这里没有整合。
15
Anonymous
15 年前
将 $pathname 中的文件模式递归更改为 $filemode

<?php

$iterator
= new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathname));

foreach(
$iterator as $item) {
chmod($item, $filemode);
}

?>
7
imoldgreg at o2 dot co dot uk
17 年前
对“neil at 11 out of 10”的代码的更新,用于更改使用 FTP 的模式。

更改:在函数中添加了正确的数组(更适合只需要连接到一个 FTP 服务器的用户),因此只需要传递模式和目录名称。

添加了八进制,以确保完整性和可预测的稳定性。

<?php
function changemode($xcite)
{
$ftp_details = array(
ftp_user_name => 'username',
ftp_user_pass => 'password',
ftp_user_root => '/public_html/',
ftp_server => 'ftp.something.org'
);

$path = "public";
$mod = intval($xcite, 8);

// 提取 FTP 详细信息(数组键作为变量名)
extract ($ftp_details);

// 设置基本连接
$conn_id = ftp_connect($ftp_server);

// 使用用户名和密码登录
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);

// 尝试将 $path 目录的 chmod 设置为 $mod
if (ftp_site($conn_id, 'CHMOD '.$mod.' '.$ftp_root.$path) !== false) {
$success=TRUE;
}
else {
$success=FALSE;
}

// 关闭连接
ftp_close($conn_id);
return
$success;
}

?>

对于像我一样寻找方法来制作“不可破解”的上传程序的人来说,这是我找到的最接近的方法,现在进行现场测试,祝您好运!
2
no at no dot es
3 年前
使用存储的字符串作为掩码很麻烦
例如:$mask 包含字符串 0755
int($mask) 不起作用(返回 755)
我找到的唯一方法是使用 octdec($mask)
5
Andrey P.
13 年前
我尝试使用 FTP 连接通过 chmod 命令更改文件夹的权限。(我需要一个可写入的文件夹来使用 php 上传图片)

我收到了以下响应
"SITE CHMOD 777 uploads: command not understood"

原因:服务器在 Windows 系统下运行,该系统不允许通过 FTP 设置文件权限。相反,在 UNIX 下运行的服务器允许这样做。

解决方案

1. 如果您的网站托管服务提供商有允许您设置文件权限的基于 Web 的控制面板,那么您需要登录并进行更改。

2. 可以联系托管服务提供商并询问他们有关此问题的信息;也许他们可以进行更改。

3. 可以更改在 UNIX 上运行服务器的托管服务提供商,并将网站保留在那里。
3
nicolas at infosoft dot inf dot br
16 年前
我使用 [email protected] 的代码,但做了一些小的修改。(Linux 符号链接)

<?php
function chmod_R($path, $filemode) {
if (!
is_dir($path))
return
chmod($path, $filemode);

$dh = opendir($path);
while ((
$file = readdir($dh)) !== false) {
if(
$file != '.' && $file != '..') {
$fullpath = $path.'/'.$file;
if(
is_link($fullpath))
return
FALSE;
elseif(!
is_dir($fullpath))
if (!
chmod($fullpath, $filemode))
return
FALSE;
elseif(!
chmod_R($fullpath, $filemode))
return
FALSE;
}
}

closedir($dh);

if(
chmod($path, $filemode))
return
TRUE;
else
return
FALSE;
}
?>
谢谢大家
3
Ambriel_Angel 在 www 点 ambriels 点 net/entry
17 年前
<?php
error_reporting
(E_ERROR | E_PARSE);
/* Makes is so Directories are not browseable to the public,
removing only the Public = Read permission, while leaving
the other chmod permissions for the file in tact.

If you have exectue already on, and read off, public viewers will only
be able to view files through links, but not browse
around to see what's inside of directories and see what
you've got laying around. */
//-------------------------------------------------------
// Get file mode
// Get file permissions supported by chmod
function getmod($filename) {
$val = 0;
$perms = fileperms($filename);
// Owner; User
$val += (($perms & 0x0100) ? 0x0100 : 0x0000); //Read
$val += (($perms & 0x0080) ? 0x0080 : 0x0000); //Write
$val += (($perms & 0x0040) ? 0x0040 : 0x0000); //Execute

// Group
$val += (($perms & 0x0020) ? 0x0020 : 0x0000); //Read
$val += (($perms & 0x0010) ? 0x0010 : 0x0000); //Write
$val += (($perms & 0x0008) ? 0x0008 : 0x0000); //Execute

// Global; World
$val += (($perms & 0x0004) ? 0x0004 : 0x0000); //Read
$val += (($perms & 0x0002) ? 0x0002 : 0x0000); //Write
$val += (($perms & 0x0001) ? 0x0001 : 0x0000); //Execute

// Misc
$val += (($perms & 0x40000) ? 0x40000 : 0x0000); //temporary file (01000000)
$val += (($perms & 0x80000) ? 0x80000 : 0x0000); //compressed file (02000000)
$val += (($perms & 0x100000) ? 0x100000 : 0x0000); //sparse file (04000000)
$val += (($perms & 0x0800) ? 0x0800 : 0x0000); //Hidden file (setuid bit) (04000)
$val += (($perms & 0x0400) ? 0x0400 : 0x0000); //System file (setgid bit) (02000)
$val += (($perms & 0x0200) ? 0x0200 : 0x0000); //Archive bit (sticky bit) (01000)

return $val;
}

//-------------------------------------------------------
// Find out if file has mode
function hasmod($perms, $permission) {

# User Read = 0400 (256), Write = 0200 (128), Execute = 0100 (64)
# Group Read = 0040 (32), Write = 0020 (16), Execute = 0010 (8)
# Public Read = 0004 (4), Write = 0002 (2), Execute = 0001 (1)

return (($perms & $permission) == $permission);
}

//-------------------------------------------------------
// Take the read option off of all the subdirectories of the included path
function pathlock($dir, $listall = false, $testrun = true) {
echo
"START @ " . date("F j, Y, h:i:s A") . "<br><br>";
echo (
$testrun ? '**Test Run Activated (no changes will be made).**<br><br>' : '**Live Run Activated.**<br><br>');
echo
$dir . " is our directory.<br><br>\n";
echo
"[...IN PROGRESS...]<br><br>";

$file_list = '';
$stack[] = $dir;

while (
$stack) {
$current_dir = array_pop($stack);
if (
$dh = opendir($current_dir)) {
while ((
$file = readdir($dh)) !== false) {
if (
$file !== '.' AND $file !== '..') {
$current_file = "{$current_dir}/{$file}";
if (
is_dir($current_file)) {
// BEG ADD PATH
$mode = getmod($current_file); //Get the mode
$HasPubRead = hasmod($mode,4);
if (
$HasPubRead || $listall) { // Can the public read this dir?
//======================================
$ch = true;
$take = 0;
// Change the mode:
if ($HasPubRead) {
$take = 4; // Value for Public Read. 4 is the same in octal and decimal.
if (!$testrun) {
$ch = chmod($current_file, $mode-$take);
}
}

echo
$current_file . ",current=" . decoct($mode) .
((
$mode!==$mode-$take) ? ",new=" . decoct($mode-$take) : '') .
(
$ch ? '' : ',FAILED') . "<br>\n";
}
// end if hasmod
// END ADD PATH
$stack[] = $current_file;
}
// if if_dir
} //if ($file !== '.' AND $file !== '..')
} //while (($file = readdir($dh)) !== false)
} //if ($dh = opendir($current_dir))
} // while ($stack)

echo "<br>COMPLETE @ " . date("F j, Y, h:i:s A") . "<br>\n";
return;
//return $path_list;
} // end function

//-------------------------------------------------------
//listall Show all folders, even one's we're not going to process?
//testrun Do a test run without making any changes
pathlock($_SERVER["DOCUMENT_ROOT"],false,true); // listall?=false, testrun?=true

?>
2
sander
15 年前
如果您想也修改目录的权限,请使用以下代码

<?php
$iterator
= new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathname), RecursiveIteratorIterator::SELF_FIRST);

foreach(
$iterator as $item) {
chmod($item, $filemode);
}
?>
2
h 点 kuppens 在 cs 点 ru 点 nl
12 年前
为了递归地修改文件和目录的权限,您可以在一步内使用以下函数。请注意,此函数有一个参数用于目录权限,另一个参数用于文件权限。
这样,您就可以对目录应用 'x' 权限,并在目录上跳过它。此函数还跳过链接。

示例用法

chmod_R( 'mydir', 0666, 0777);

使 mydir/ 目录中的所有文件和目录对每个人都可访问,但不使文件可执行。

我猜想对于非常深层的嵌套目录来说,使用 PHP 进行递归可能会出现问题,但我可能错了,因为我从未对此进行过调查。

<?php
function chmod_R($path, $filemode, $dirmode) {
if (
is_dir($path) ) {
if (!
chmod($path, $dirmode)) {
$dirmode_str=decoct($dirmode);
print
"无法应用文件模式 '$dirmode_str' 到目录 '$path'\n";
print
" `-> 目录 '$path' 将从递归 chmod 中跳过\n";
return;
}
$dh = opendir($path);
while ((
$file = readdir($dh)) !== false) {
if(
$file != '.' && $file != '..') { // 跳过自身和父级指向的目录
$fullpath = $path.'/'.$file;
chmod_R($fullpath, $filemode,$dirmode);
}
}
closedir($dh);
} else {
if (
is_link($path)) {
print
"链接 '$path' 被跳过\n";
return;
}
if (!
chmod($path, $filemode)) {
$filemode_str=decoct($filemode);
print
"无法应用文件模式 '$filemode_str' 到文件 '$path'\n";
return;
}
}
}
?>
1
webmaster 在 danopia 点 5gigs 点 com
17 年前
感谢您的代码,"imoldgreg 在 o2 点 co 点 uk"。我正在安装脚本中使用它,该脚本必须修改一堆文件。我发现使用相同的连接来执行每个命令更快,如下所示。

<?php

// 感谢 "imoldgreg 在 o2 点 co 点 uk" 提供的 '通过 FTP 修改权限' 脚本的基本代码。

function chmod_open()
{
// 使用您自己的 FTP 信息
$ftp_user_name = '[email protected]';
$ftp_user_pass = 'XXXXXXXXXX';
$ftp_root = '/';
$ftp_server = 'localhost';
$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
return
$conn_id;
}

function
chmod_file($conn_id, $permissions, $path)
{
if (
ftp_site($conn_id, 'CHMOD ' . $permissions . ' ' . $ftp_root . $path) !== false)
{
return
TRUE;
}
else
{
return
FALSE;
}
}

function
chmod_close($conn_id)
{
ftp_close($conn_id);
}

// 修改所需设置文件的权限

// 连接到 FTP
$conn_id = chmod_open();

// 修改每个文件的权限并输出结果
echo chmod_file($conn_id, 777, 'master/cache/') ? '权限修改成功!' : '错误';
echo
chmod_file($conn_id, 777, 'master/files/') ? '权限修改成功!' : '错误';
echo
chmod_file($conn_id, 777, 'master/store/') ? '权限修改成功!' : '错误';
echo
chmod_file($conn_id, 766, 'master/config.php') ? '权限修改成功!' : '错误';
echo
chmod_file($conn_id, 777, 'master/images/avatars/upload/') ? '权限修改成功!' : '错误';

// 关闭连接
chmod_close($conn_id);

?>

在这里,相同的 FTP 连接用于每个 CHMOD 命令,从而缩短了执行时间。这对我来说至关重要,因为我的脚本也在复制一堆文件。
To Top