前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >LINQ(集成查询)语言官方使用教程

LINQ(集成查询)语言官方使用教程

原创
作者头像
Power
发布于 2025-04-03 08:24:25
发布于 2025-04-03 08:24:25
8100
代码可运行
举报
运行总次数:0
代码可运行

简介

本教程将介绍 .NET Core 和 C# 语言的功能。 你将了解如何执行以下操作:

  • 使用 LINQ 生成序列。
  • 编写可轻松用于 LINQ 查询的方法。
  • 区分及早计算和惰性计算。

你将通过生成应用程序来了解如何执行这些操作,应用程序体现了所有魔术师都具备的一项基本技能,即完美洗牌。 简而言之,完美洗牌这项技能是指,将一副纸牌分成两半,然后两手各拿一半交错洗牌(一张隔一张),以便重新生成原来的一副纸牌。

魔术师之所以要掌握这项技能是因为,每次洗牌后每张纸牌的位置已知,且顺序为重复模式。

考虑到你的目的,数据序列控制起来就会非常轻松。 生成的应用程序会构造一副纸牌,然后执行一系列洗牌操作,每次都会输出序列。 还可以将更新后的顺序与原始顺序进行比较。

在此教程中,将执行多步操作。 执行每步操作后,都可以运行应用程序,并查看进度。 还可参阅 dotnet/samples GitHub 存储库中的完整示例

先决条件

必须将计算机设置为运行 .Net Core。 有关安装说明,请访问 .NET Core 下载页。 可以在 WindowsUbuntu Linux、OS X 或 Docker 容器中运行此应用程序。 必须安装常用的代码编辑器。 在以下说明中,我们使用的是开放源代码跨平台编辑器 Visual Studio Code。 不过,你可以使用习惯使用的任意工具。

创建应用程序

第一步是新建应用程序。 打开命令提示符,然后新建应用程序的目录。 将新建的目录设为当前目录。 在命令提示符处,键入命令 dotnet new console。 这将为基本的“Hello World”应用程序创建起始文件。

创建数据集

开始前,请确保下列行在 dotnet new console 生成的 Program.cs 文件的顶部:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;

如果这三行(using 语句)未在该文件的顶部,程序将无法编译。

现在已具备所需的所有引用,接下来可以考虑一副扑克牌是由什么构成的。 通常一副扑克牌包含四种花色,每种花色包含 13 个值。 通常情况下,你可能会立即考虑创建一个 Card 类,然后手动填充一组 Card 对象。 相对于通常的方式,使用 LINQ 创建一副扑克牌更加简捷。 可以创建两个序列来分别表示花色和点数,而非创建 Card 类。 创建两个非常简单的迭代器方法,用于将级别和花色生成为 IEnumerable<T> 字符串:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
// The Main() method

static IEnumerable<string> Suits()
{
    yield return "clubs";
    yield return "diamonds";
    yield return "hearts";
    yield return "spades";
}

static IEnumerable<string> Ranks()
{
    yield return "two";
    yield return "three";
    yield return "four";
    yield return "five";
    yield return "six";
    yield return "seven";
    yield return "eight";
    yield return "nine";
    yield return "ten";
    yield return "jack";
    yield return "queen";
    yield return "king";
    yield return "ace";
}

将它们置于 Main 文件的 Program.cs 方法的下面。 这两种方法都利用 yield return 语法在运行时生成序列。 编译器会生成对象来实现 IEnumerable<T>,并在有请求时生成字符串序列。

现在使用这些迭代器创建一副扑克牌。 将 LINQ 查询置于 Main 方法中。 具体如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
static void Main(string[] args)
{
    var startingDeck = from s in Suits()
                       from r in Ranks()
                       select new { Suit = s, Rank = r };

    // Display each card that we've generated and placed in startingDeck in the console
    foreach (var card in startingDeck)
    {
        Console.WriteLine(card);
    }
}

多个 from 子句生成 SelectMany,用于将第一个和第二个序列中的所有元素合并成一个序列。 考虑到我们的目的,顺序非常重要。 第一个源序列(花色)中的首个元素与第二个序列(等级)中的每个元素结合使用。 这就生成了第一个花色的所有十三张纸牌。 对第一个序列(花色)中的每个元素重复此过程。 最后生成按花色排序(后跟值)的一副纸牌。

务必注意,无论是选择使用上文所用的查询语法编写 LINQ,还是使用方法语法,始终都可以从一种语法形式转至另一种。 可使用方法语法编写使用查询语法编写的上述查询,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var startingDeck = Suits().SelectMany(suit => Ranks().Select(rank => new { Suit = suit, Rank = rank }));

编译器会将使用查询语法编写的 LINQ 语句转换为等效的方法调用语法。 因此无论选择哪种语法,两种查询版本生成的结果相同。 选择最适合你的情况的语法:例如,若所在的工作团队中的某些成员不擅长方法语法,则尽量首选使用查询语法。

此时,运行已生成的示例。 将显示一副纸牌中的所有 52 张纸牌。 在调试器模式下运行此示例来观察 Suits() 和 Ranks() 方法的执行情况,你可能会觉得非常有用。 可以清楚地看到,每个序列中的所有字符串仅在需要时生成。

操作顺序

接下来重点介绍如何洗牌。 正确洗牌的第一步是将一副扑克牌分成两半。 LINQ API 包含的 Take 和 Skip 方法提供了这种功能。 将它们置于 foreach 循环的下面:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
public static void Main(string[] args)
{
    var startingDeck = from s in Suits()
                       from r in Ranks()
                       select new { Suit = s, Rank = r };

    foreach (var c in startingDeck)
    {
        Console.WriteLine(c);
    }

    // 52 cards in a deck, so 52 / 2 = 26
    var top = startingDeck.Take(26);
    var bottom = startingDeck.Skip(26);
}

但标准库中没有可供使用的洗牌方法,因此必须自行编写。 将要创建的洗牌方法体现了要对基于 LINQ 的程序执行的几种操作,因此我们将逐步介绍此过程的每个部分。

需要编写几种特殊的方法,我们称之为IEnumerable<T>扩展方法,来添加一些功能,以便于与 LINQ 查询返回的 交互。 简而言之,扩展方法是具有特殊用途的静态方法,借助它无需修改你想要为其添加功能的已有原始类型,即可向其添加功能。

向程序添加新的静态类文件(名称为 Extensions.cs),以用于存放扩展方法,然后开始生成第一个扩展方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Extensions.cs
using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqFaroShuffle
{
    public static class Extensions
    {
        public static IEnumerable<T> InterleaveSequenceWith<T>(this IEnumerable<T> first, IEnumerable<T> second)
        {
            // Your implementation will go here soon enough
        }
    }
}

仔细观察方法签名,尤其是参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static IEnumerable<T> InterleaveSequenceWith<T> (this IEnumerable<T> first, IEnumerable<T> second)

可以发现,在扩展方法的第一个自变量中添加了 this 修饰符。 也就是说,调用扩展方法,就像是第一个自变量类型的成员方法一样。 此方法声明还遵循标准惯用做法,其中输入和输出类型为 IEnumerable<T>。 遵循这种做法,可以将 LINQ 方法链在一起,从而执行更复杂的查询。

正常情况下,将扑克牌分为两半后,需要将这两半合并在一起。 在代码中,这意味着一次性地枚举通过 Take 和 Skip 获得的两个序列,interleaving 元素,并创建一个序列:即现在洗牌后的扑克牌。 必须了解 IEnumerable<T> 的工作原理,才能编写处理两个序列的 LINQ 方法。

IEnumerable<T> 接口有一个方法 (GetEnumerator)。 GetEnumerator 返回的对象包含用于移动到下一个元素的方法,以及用于检索序列中当前元素的属性。 将使用这两个成员来枚举集合并返回元素。 由于此交错方法是迭代器方法,因此将使用上面的 yield return 语法,而不用生成并返回集合。

下面是此方法的实现代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static IEnumerable<T> InterleaveSequenceWith<T>
    (this IEnumerable<T> first, IEnumerable<T> second)
{
    var firstIter = first.GetEnumerator();
    var secondIter = second.GetEnumerator();

    while (firstIter.MoveNext() && secondIter.MoveNext())
    {
        yield return firstIter.Current;
        yield return secondIter.Current;
    }
}

至此,你已编写好这个方法,请回到 Main 方法,并进行一次洗牌:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
public static void Main(string[] args)
{
    var startingDeck = from s in Suits()
                       from r in Ranks()
                       select new { Suit = s, Rank = r };

    foreach (var c in startingDeck)
    {
        Console.WriteLine(c);
    }

    var top = startingDeck.Take(26);
    var bottom = startingDeck.Skip(26);
    var shuffle = top.InterleaveSequenceWith(bottom);

    foreach (var c in shuffle)
    {
        Console.WriteLine(c);
    }
}

比较

进行多少次洗牌才能恢复一副纸牌的原始顺序? 若要解决这个问题,需要编写用于确定两个序列是否相等的方法。 编写好此方法后,需要循环执行用于洗牌的代码,看看一副纸牌何时才能恢复原始顺序。

编写用于确定两个序列是否相等的方法应该很简单。 此方法的结构与你编写的洗牌方法类似。 不同之处在于,这一次将比较每个序列的匹配元素,而不是 yield return 每个元素。 枚举整个序列后,如果每个元素都一致,那么序列就是相同的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static bool SequenceEquals<T>
    (this IEnumerable<T> first, IEnumerable<T> second)
{
    var firstIter = first.GetEnumerator();
    var secondIter = second.GetEnumerator();

    while ((firstIter?.MoveNext() == true) && secondIter.MoveNext())
    {
        if ((firstIter.Current is not null) && !firstIter.Current.Equals(secondIter.Current))
        {
            return false;
        }
    }

    return true;
}

这反映了另一种 LINQ 惯用做法,即终端方法。 此类方法需要将序列(或在此示例中,为两个序列)用作输入,并返回一个标量值。 使用终端方法时,它们始终是 LINQ 查询方法链中最后的方法,因此其名称为“终端”。

使用此类方法来确定一副纸牌何时恢复原始顺序时,就可以了解实际效果。 循环执行洗牌代码,通过应用 SequenceEquals() 方法确定序列已恢复原始顺序时停止执行。 你会发现,此类方法始终是任何查询中的最后一个方法,因为返回的是一个值,而不是一个序列:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
static void Main(string[] args)
{
    // Query for building the deck

    // Shuffling using InterleaveSequenceWith<T>();

    var times = 0;
    // We can re-use the shuffle variable from earlier, or you can make a new one
    shuffle = startingDeck;
    do
    {
        shuffle = shuffle.Take(26).InterleaveSequenceWith(shuffle.Skip(26));

        foreach (var card in shuffle)
        {
            Console.WriteLine(card);
        }
        Console.WriteLine();
        times++;

    } while (!startingDeck.SequenceEquals(shuffle));

    Console.WriteLine(times);
}

运行现有的代码,并记录每次洗牌时扑克牌的重写排列方式。 进行 8 次洗牌后(迭代 do-while 循环),扑克牌恢复从最初的 LINQ 查询首次创建它时的原始配置。

优化

到目前为止,你已生成的示例执行的是向外洗牌,即每次洗牌时第一张和最后一张纸牌保持不变。 让我们来做一点改变,改为使用向内洗牌,改变全部 52 张纸牌的位置。 向内洗牌是指,交错一副纸牌时,将后一半中的第一张纸牌变成一副纸牌中的第一张纸牌。 也就是说,上半部分中的最后一张纸牌变成一副纸牌中的最后一张纸牌。 这是对单行代码的简单更改。 交换 Take 和 Skip 的位置,来更新当前洗牌查询。 这会更改一副纸牌的上半部分和下半部分的顺序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
shuffle = shuffle.Skip(26).InterleaveSequenceWith(shuffle.Take(26));

再次运行程序,你会发现需要进行 52 次迭代才能恢复一副纸牌的原始顺序。 随着程序的继续运行,你还会开始注意到一些非常严重的性能下降问题发生。

导致这种情况出现的原因有很多。 可以解决导致性能下降的主要原因之一:延迟计算的使用效率低下。

简单来说,延迟计算是指直至需要语句的值时才会执行语句计算。 LINQ 查询属于延迟计算的语句。 仅当有元素请求时才生成序列。 通常情况下,这是 LINQ 的主要优势所在。 不过,在诸如此程序之类的用例中,这就会导致执行时间指数式增长。

应该记得原来的一副纸牌是使用 LINQ 查询生成的。 每次洗牌操作是通过对上一副纸牌执行三次 LINQ 查询进行。 所有这些操作均采用惰性执行方式。 也就是说,每当有序列请求时,才会再次执行这些操作。 执行到第 52 次迭代时,就已经重新生成很多很多次原来的一副纸牌。 让我们来编写一个日志方法来阐明此行为。 然后,你就可以解决此问题。

在 Extensions.cs 文件中输入或复制下面的方法。 此扩展方法会在项目目录中新建一个名称为 debug.log 的文件,并将当前正在执行的查询记录到日志文件中。 可以将此扩展方法追加到任何查询中,以标记查询已执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static IEnumerable<T> LogQuery<T>
    (this IEnumerable<T> sequence, string tag)
{
    // File.AppendText creates a new file if the file doesn't exist.
    using (var writer = File.AppendText("debug.log"))
    {
        writer.WriteLine($"Executing Query {tag}");
    }

    return sequence;
}

你将看到 File 下显示红色波浪线,这表示它不存在。 它将不编译,因为编译器无法识别 File。 要解决此问题,请务必在 Extensions.cs 中第一行的下面添加以下代码行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.IO;

这应可解决问题,随后红色错误将消失。

接下来,使用日志消息来检测每个查询的定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Program.cs
public static void Main(string[] args)
{
    var startingDeck = (from s in Suits().LogQuery("Suit Generation")
                        from r in Ranks().LogQuery("Rank Generation")
                        select new { Suit = s, Rank = r }).LogQuery("Starting Deck");

    foreach (var c in startingDeck)
    {
        Console.WriteLine(c);
    }

    Console.WriteLine();
    var times = 0;
    var shuffle = startingDeck;

    do
    {
        // Out shuffle
        /*
        shuffle = shuffle.Take(26)
            .LogQuery("Top Half")
            .InterleaveSequenceWith(shuffle.Skip(26)
            .LogQuery("Bottom Half"))
            .LogQuery("Shuffle");
        */

        // In shuffle
        shuffle = shuffle.Skip(26).LogQuery("Bottom Half")
                .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
                .LogQuery("Shuffle");

        foreach (var c in shuffle)
        {
            Console.WriteLine(c);
        }

        times++;
        Console.WriteLine(times);
    } while (!startingDeck.SequenceEquals(shuffle));

    Console.WriteLine(times);
}

请注意,不是每次访问查询都会生成日志。 只有在创建原始查询时,才会生成日志。 程序的运行时间仍然很长,但现在知道原因了。 如果对在启用日志记录的情况下运行向内洗牌失去了耐心,请切换回向外洗牌。 但仍会看到惰性计算效果。 在一次运行中,共执行 2592 次查询,包括生成所有值和花色。

可以提高此处的代码性能,以减少执行次数。 一个简单的修复方法是缓存构造扑克牌的原始 LINQ 查询的结果。 目前,每当 do-while 循环进行迭代时,需要反复执行查询,每次都要重新构造扑克牌并进行洗牌。 可以利用 LINQ 方法 ToArray 和 ToList 来缓存扑克牌;将这两个方法追加到查询时,它们将执行你已告知它们要执行的同种操作,而现在它们会将结果存储在数组或列表中,具体取决于选择调用的方法。 将 LINQ 方法 ToArray 追加到两个查询中,并再次运行程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void Main(string[] args)
{
    IEnumerable<Suit>? suits = Suits();
    IEnumerable<Rank>? ranks = Ranks();

    if ((suits is null) || (ranks is null))
        return;

    var startingDeck = (from s in suits.LogQuery("Suit Generation")
                        from r in ranks.LogQuery("Value Generation")
                        select new { Suit = s, Rank = r })
                        .LogQuery("Starting Deck")
                        .ToArray();

    foreach (var c in startingDeck)
    {
        Console.WriteLine(c);
    }

    Console.WriteLine();

    var times = 0;
    var shuffle = startingDeck;

    do
    {
        /*
        shuffle = shuffle.Take(26)
            .LogQuery("Top Half")
            .InterleaveSequenceWith(shuffle.Skip(26).LogQuery("Bottom Half"))
            .LogQuery("Shuffle")
            .ToArray();
        */

        shuffle = shuffle.Skip(26)
            .LogQuery("Bottom Half")
            .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
            .LogQuery("Shuffle")
            .ToArray();

        foreach (var c in shuffle)
        {
            Console.WriteLine(c);
        }

        times++;
        Console.WriteLine(times);
    } while (!startingDeck.SequenceEquals(shuffle));

    Console.WriteLine(times);
}

现在向外洗牌下降到 30 次查询。 再次运行向内洗牌程序,改善情况类似:现在它执行 162 次查询。

请注意,此示例旨在突出显示延迟计算可能会导致性能下降的用例。 了解延迟计算会在何处影响代码性能至关重要,但了解并非所有查询应及早运行也同等重要。 未使用 ToArray 会导致性能损失,这是因为每次重新排列一副纸牌都要以先前的排列为依据。 使用惰性计算意味着一副纸牌的每个新配置都以原来的一副纸牌为依据,甚至在执行生成 startingDeck 的代码时,也不例外。 这会导致大量额外的工作。

在实践中,一些算法使用及早计算的效果较好,另一些算法使用延迟计算的效果较好。 对于日常使用,如果数据源为单独进程(如数据库引擎),通常更好的选择是使用延迟计算。 对于数据库,使用延迟计算,更复杂的查询可以只对数据库进程执行一次往返,然后返回至剩余的代码。 无论选择使用延迟计算还是及早计算,LINQ 均可以灵活处理,因此请衡量自己的进程,然后选择可为你提供最佳性能的计算种类。

结束语

在此项目中介绍了下列内容:

  • 使用 LINQ 查询,来将数据聚合到有意义的序列中
  • 编写扩展方法,来将自己的自定义功能添加到 LINQ 查询
  • 查找 LINQ 查询可能会在其中遇到性能问题(如速度下降)的代码区域
  • 与 LINQ 查询相关的延迟计算和及早计算,以及它们对查询性能的影响

除 LINQ 外,还简单介绍了魔术师用于扑克牌魔术的一个技术。 魔术师之所以采用完美洗牌是因为,可以控制每张纸牌在一副纸牌中的移动。 现在你了解了,也不要告诉其他人以免破坏他们的兴致!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
PHP-FPM RCE (CVE-2019-11043)
安全研究员 Andrew Danau 在解决一道 CTF 题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常,疑似存在漏洞。当 Nginx 将包含 PATH_INFO 为空的参数通过 FastCGI 传递给 PHP-FPM 时,PHP-FPM 接收处理的过程中存在逻辑问题。通过精心构造恶意请求可以对 PHP-FPM 进行内存污染,进一步可以复写内存并修改 PHP-FPM 配置,实现远程代码执行。
wywwzjj
2023/05/09
1K0
PHP-FPM RCE (CVE-2019-11043)
LAMP-PHP-fpm服务器配置
yum -y groupinstall "Desktop Platform Development"
星哥玩云
2022/07/01
1.2K0
LAMP-PHP-fpm服务器配置
PHP-fpm 远程代码执行漏洞(CVE-2019-11043)分析
国外安全研究员 Andrew Danau在解决一道 CTF 题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常,疑似存在漏洞。
知道创宇云安全
2019/10/28
1.2K0
PHP-fpm 远程代码执行漏洞(CVE-2019-11043)分析
PHP-FPM 性能配置优化
php-fpm 全称是 PHP FastCGI Process Manager 的简称,从名字可得知,是一个 FastCGI 的管理器。
南山竹
2024/06/12
1810
PHP-FPM 性能配置优化
LNMP架构介绍、安装PHP(php-fpm)
CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。 CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,tcl等。
阿dai学长
2019/04/03
1.9K0
fpm源码阅读(1)
FastCGI是Web服务器(如:Nginx、Apache)和处理程序之间的一种通信协议,它是与Http类似的一种应用层通信协议,注意:它只是一种协议!
golangLeetcode
2022/08/02
4860
Centos7 安装配置 PHP7 Nginx 并部署开源后台系统Fasadmin
1、查看是否安装过Nginx rpm -qa|grep -E "nginx" 2、安装Nginx前需要提前安装以下这些依赖 2.1、查看gcc版本 gcc -v 若有内容输出说明已安装了gcc。否则,需使用以下命令进行安装。 yum -y install gcc 2.2、pcre、pcre-devel安装 yum install -y pcre pcre-devel 2.3、zlib安装 yum install -y zlib zlib-devel 2.4、安装openssl yum ins
游离于山间之上的Java爱好者
2022/09/21
4850
Centos7 安装配置 PHP7 Nginx 并部署开源后台系统Fasadmin
PHP-FPM
PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置。
友儿
2022/09/11
9140
CVE-2019-11043: PHP 7 RCE漏洞分析
研究人员在PHP 7中找出有个远程代码执行(RCE)漏洞,该漏洞CVE编号为CVE-2019-11043。攻击者利用该漏洞只需要访问通过精心伪造的URL就可以在服务器上运行命令。
猿哥
2019/10/29
2.1K0
LNMP之Php的安装配置
此配置的编译参数是: ./configure --prefix=/opt/php7.2.3 --with-openssl --with-zlib --with-curl --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-mbstring --with-libxml-dir --enable-soap --enable-sockets --with-xmlrpc --with-iconv-dir
用户1173509
2018/03/28
2K0
LNMP之Php的安装配置
CVE-2019-11043PHP-FPM在Nginx特定配置下远程代码执行漏洞复现
9月26日,PHP官方发布漏洞通告,提到Nginx与php-fpm服务器上存在的一处高危漏洞,由于Nginx的fastcgi_split_path_info模块在处理带 %0a 的请求时,对换行符 \n 处置不当使得将PATH_INFO值置为空,从而导致可以通过FCGI_PUTENV与PHP_VALUE相结合,修改当前的php-fpm进程中的php配置。在特殊构造的配置生效的情况下可以触发任意代码执行。目前开源社区已有漏洞Poc公开。
墙角睡大觉
2019/10/30
1.3K0
CVE-2019-11043PHP-FPM在Nginx特定配置下远程代码执行漏洞复现
PHP优化设置
1.查询php配置文件 find / -name php.ini 可以输出如下: /etc/php.ini 配置如下: ; Start a new pool named 'www'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) [www] ; Per pool prefix ; It only applies on the following
Zach
2019/12/30
5.9K0
LNMP环境下Nginx中php-fpm的配置文件讲解
一、nginx配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 user nobody nobody; worker_processes 2; error_log /usr/local/nginx/logs/nginx_error.log crit; pid /usr/local/nginx/
老七Linux
2018/05/09
2K1
linux学习第四十八篇:php-fpm的pool,php-fpm慢执行日志,定义open_basedir,php-fpm进程管理
php-fpm的pool Nginx可以配置多个虚拟主机,php-fpm同样也支持配置多个pool,每一个pool可以监听一个端口,也可以监听一个socket。 vim /usr/local/php/etc/php-fpm.conf 在[global]部分增加: include = etc/php-fpm.d/*.conf 创建php-fpm.d目录: mkdir /usr/local/php/etc/php-fpm.d 进入目录: cd /usr/local/php/etc/php-fp
用户1215343
2018/02/05
7440
linux学习第四十八篇:php-fpm的pool,php-fpm慢执行日志,定义open_basedir,php-fpm进程管理
【PHP7源码分析】PHP中$_POST揭秘
前几天的工作中,需要通过curl做一次接口测试。让我意外的是,通过$_POST竟然无法获取到Content-Type是application/json的http请求的body参数。 查了下php官网对$_POST的描述,的确是这样。 后来通过file_get_contents("php://input")获取到了原始的http请求body,然后对参数进行json_decode解决了接口测试的问题。事后,脑子里面冒出了挺多问题:
桶哥
2019/06/04
6.3K0
【PHP7源码分析】PHP中$_POST揭秘
12.21 php-fpm的pool
php-fpm的pool目录概要 vim /usr/local/php/etc/php-fpm.conf//在[global]部分增加 include = etc/php-fpm.d/*.conf mkdir /usr/local/php/etc/php-fpm.d/ cd /usr/local/php/etc/php-fpm.d/ vim www.conf //内容如下 [www] listen = /tmp/www.sock listen.mode=666 user = php-fpm group =
运维小白
2018/02/06
1.5K0
[漏洞预警]PHP-FPM在Nginx的特定环境下的任意代码执行漏洞
2019年10月22日在国外上某技术大牛公开了在PHP-FPM中新修补的RCE。
洛米唯熊
2019/10/25
1.2K0
[漏洞预警]PHP-FPM在Nginx的特定环境下的任意代码执行漏洞
php-fpm在nginx特定环境下的任意代码执行漏洞(CVE-2019-11043)
在长亭科技举办的 Real World CTF 中,国外安全研究员 Andrew Danau 在解决一道 CTF 题目时发现,向目标服务器 URL 发送%0a符号时,服务返回异常,疑似存在漏洞。
天钧
2019/11/11
8721
php-fpm在nginx特定环境下的任意代码执行漏洞(CVE-2019-11043)
Web安全 | Fastcgi 协议分析与 PHP-FPM 攻击方法
本文总结了一下 Fastcgi 原理以及攻击方法,若有不当之处还望各位大佬多多指教。
HACK学习
2021/06/24
2.5K0
Web安全 | Fastcgi 协议分析与 PHP-FPM 攻击方法
学习笔记0518----nginx和php-fpm配置
负载均衡在服务端开发中算是一个比较重要的特性。因为Nginx除了作为常规的Web服务器外,还会被大规模的用于反向代理前端,因为Nginx的异步框架可以处理很大的并发请求,把这些并发请求hold住之后就可以分发给后台服务端(backend servers,也叫做服务池, 后面简称backend)来做复杂的计算、处理和响应,这种模式的好处是相当多的:隐藏业务主机更安全,节约了公网IP地址,并且在业务量增加的时候可以方便地扩容后台服务器。
嘻哈记
2020/11/24
1.8K0
相关推荐
PHP-FPM RCE (CVE-2019-11043)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档