[{"content":"Recently I&rsquo;ve been using Hetzner Cloud with IPv6 only. I installed Docker and deployed some services. With the default settings of Docker, containers cannot access the IPv6 only network on the host.\nThe reason is that Docker daemon would normally just assign a IPv4 private CIDR. However, enabling IPv6 is relatively easy. Edit your \/etc\/docker\/daemon.json:\n{ &#34;ipv6&#34;: true, &#34;fixed-cidr-v6&#34;: &#34;fd00:db8:1::\/64&#34;, &#34;experimental&#34;: true, &#34;ip6tables&#34;: true, &#34;default-address-pools&#34;: [ { &#34;base&#34;: &#34;172.17.0.0\/16&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;172.18.0.0\/16&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;172.19.0.0\/16&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;172.20.0.0\/14&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;172.24.0.0\/14&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;172.28.0.0\/14&#34;, &#34;size&#34;: 16 }, { &#34;base&#34;: &#34;192.168.0.0\/16&#34;, &#34;size&#34;: 20 }, { &#34;base&#34;: &#34;fd00:db8::\/104&#34;, &#34;size&#34;: 112 } ] } Then set IPv6 in docker-compose.yaml:\nnetworks: default: enable_ipv6: true Done!\nReference: https:\/\/docs.docker.com\/config\/daemon\/ipv6\/\n","permalink":"https:\/\/wi1dcard.dev\/posts\/docker-in-ipv6-only-network\/","summary":"Recently I&rsquo;ve been using Hetzner Cloud with IPv6 only. I installed Docker and deployed some services. With the default settings of Docker, containers cannot access the IPv6 only network on the host.","title":"Docker in IPv6-Only Network"},{"content":"\u4f18\u8d28\u7684 Git commit message \u548c Changelog \u4e0d\u4ec5\u53ef\u4ee5\u8ba9\u534f\u4f5c\u8005\u4eec\u4e00\u76ee\u4e86\u7136\u5730\u4e86\u89e3\u7248\u672c\u53d8\u66f4\uff0c\u66f4\u80fd\u5e2e\u52a9\u4f60\u5feb\u901f\u56de\u5fc6\u66fe\u7ecf\u7684\u4fee\u6539\u3002\u56e0\u6b64\uff0c\u5408\u7406\u5730\u4f7f\u7528\u82f1\u8bed\u52a8\u8bcd\u3001\u901a\u8fc7\u300c\u4e00\u53e5\u8bdd\u300d\u7cbe\u51c6\u5730\u6982\u62ec\u505a\u4e86\u4ec0\u4e48\u4e8b\u3001\u7f16\u5199\u6613\u8bfb\u6613\u61c2\u7684\u63cf\u8ff0\u5c31\u663e\u5f97\u5c24\u4e3a\u91cd\u8981\u3002\u672c\u6587\u76ee\u7684\u662f\u7d22\u5f15\u548c\u603b\u7ed3\u5e38\u7528\u7684\u52a8\u8bcd\u5217\u8868\uff0c\u5185\u5bb9\u4ec5\u51ed\u6211\u4e2a\u4eba\u7ecf\u9a8c\u4ee5\u53ca\u6709\u9650\u7684\u67e5\u9605\u8d44\u6599\uff0c\u8bf7\u7ed3\u5408\u5b9e\u9645\u60c5\u51b5\u4f7f\u7528\u3002\nUpgrade\uff1a\u5347\u7ea7\uff08\u7248\u672c\u3001\u7b49\u7ea7\u7b49\uff09 \u4f8b\u5982\uff1a\n Upgrade Kubernetes to v1.20.0. Upgrade Subscan API user example@gmail.com to the professional plan.  \u53cd\u4e49\u8bcd\uff1aDowngrade\uff0c\u4f8b\u5982\uff1a\n Downgrade Kubernetes to v1.19.0. Downgrade Subscan API user example@gmail.com to the free plan.  \u5bf9\u4e8e\u300c\u5347\u7ea7\uff08\u7248\u672c\uff09\u300d\u4e00\u4e49\uff0c\u6839\u636e\u5b9e\u9645\u573a\u666f\uff0c\u4e5f\u53ef\u4f7f\u7528 Rollback\u3001Revert \u7b49\u4f5c\u4e3a\u53cd\u4e49\u8bcd\u3002\nRollback\uff1a\u56de\u6eda \u5f80\u5f80\u7528\u4e8e\u5347\u7ea7\u7248\u672c\u540e\uff0c\u9700\u8981\u64a4\u56de\u5230\u539f\u7248\u672c\u7684\u60c5\u51b5\uff1b\u4f8b\u5982\uff1a\n Rollback Kubernetes to v1.19.0.  Revert\uff1a\u64a4\u56de\uff0c\u6062\u590d\uff08\u5230\u5148\u524d\u72b6\u6001\uff09 \u4f8b\u5982\uff1a\n Revert upgrading Kubernetes. Revert commit &ldquo;abcd123&rdquo;.  Bump\uff1a\u66f4\u8fed\u3001\u4e0a\u8c03\u7248\u672c\u53f7\u4e3a\u5168\u65b0\u7684\u503c \u4f8b\u5982\uff1a\n Bump Kubernetes v1.20.0. Bump Kubernetes version to v1.20.0.  Update\uff1a\u66f4\u65b0 \u6b64\u5904\u6240\u6307\u300c\u66f4\u65b0\u300d\u5e76\u975e\u300c\u5347\u7ea7\u300d\uff0c\u5f80\u5f80\u53ea\u6709\u300c\u66f4\u65b0\u201c\u539f\u59cb\u6216\u9648\u65e7\u4fe1\u606f\u201d\u4e3a\u201c\u65b0\u4fe1\u606f\u201d\u300d\u7684\u542b\u4e49\uff1b\u9519\u8bef\u4f8b\u5b50\uff1a\n \u274c Update Kubernetes to v1.20.0.  \u6b63\u786e\u4f8b\u5b50\uff1a\n Update cert-manager&rsquo;s CRDs. Update the Grafana dashboards to follow the upstream changes.  Change\uff1a\u66f4\u6539 \u4e0e Update \u7c7b\u4f3c\uff0c\u90fd\u6709\u300c\u66f4\u6539\u4fe1\u606f\u300d\u7684\u542b\u4e49\uff0c\u4f46 Change \u5e76\u672a\u9690\u542b\u300c\u9648\u65e7\u4fe1\u606f \u2192 \u65b0\u4fe1\u606f\u300d\uff0c\u56e0\u6b64\u5b83\u7684\u7528\u9014\u66f4\u52a0\u5e7f\u6cdb\uff1bChange \u4e5f\u53ef\u7528\u4e8e\u300c\u65b0\u4fe1\u606f \u2192 \u8001\u4fe1\u606f\u300d\u6216\u4ec5\u4ec5\u662f\u300c\u66f4\u6539\u300d\uff08\u66f4\u6539\u524d\u540e\u5e76\u65e0\u65b0\u65e7\u4e4b\u5206\uff09\uff0c\u4f8b\u5982\uff1a\n Change the Subscan API plan back to free for the user example@gmail.com. Change the PVC size of the Darwinia node to 100 GiB.\uff08\u672c\u4f8b\u4e5f\u53ef\u4f7f\u7528 Update\uff09  Fix\uff1a\u4fee\u590d \u4f8b\u5982\uff1a\n  Fix minor issues.\n  Fix the incorrect MySQL password.\n  Fix Subscan not reading environment variables.\n\u672c\u4f8b\u4e2d\u6587\u662f\u300c\u4fee\u590d Subscan \u4e0d\u8bfb\u73af\u5883\u53d8\u91cf\u7684\u95ee\u9898\u300d\u3002\u82f1\u6587\u539f\u6587\u7701\u7565\u4e86\u300c\u7684\u95ee\u9898\u300d\uff0c\u5728\u4f7f\u7528 Fix \u65f6\uff0c\u7ecf\u5e38\u53ef\u4ee5\u7701\u7565\u4e2d\u6587\u300c\u7684\u95ee\u9898\u300d\u540e\u7f00\uff0c\u4f8b\u5982\uff1a\n \ud83e\udd28 Fix Subscan&rsquo;s problem which is not reading environment variables. \u2192 \ud83d\ude00 \u672c\u4f8b\u539f\u6587 \ud83e\udd28 Fix the issue of missing the API key. \u2192 \ud83d\ude00 Fix missing the API key.    Install\uff1a\u5b89\u88c5 \u4f8b\u5982\uff1a\n  Install Nginx Ingress Controller in the cluster.\n&ldquo;Nginx Ingress Controller&rdquo; \u4e3a\u4e13\u6709\u540d\u8bcd\uff0c\u5176\u524d\u65e0\u9700\u5e26 the\uff1b\u800c cluster \u4e3a\u975e\u4e13\u6709\u540d\u8bcd\uff0c\u5176\u524d\u901a\u5e38\u5e26 the\uff08\u4f46\u4e5f\u6709\u975e\u4e13\u6709\u540d\u8bcd\u4e0d\u9700\u8981\u5e26 the \u7684\u60c5\u51b5\uff09\u3002\n  Install the requirements of Nginx Ingress Controller.\n&ldquo;requirements&rdquo; \u4e3a\u975e\u4e13\u6709\u540d\u8bcd\uff0c\u5176\u524d\u901a\u5e38\u5e26 the\u3002\n  Deploy\uff1a\u90e8\u7f72 \u5728 DevOps \u573a\u666f\u4e2d\u4e0e Install \u7c7b\u4f3c\uff0c\u67d0\u4e9b\u60c5\u51b5\u53ef\u4ee5\u4e92\u6362\uff0c\u4f8b\u5982\uff1a\n Deploy Nginx Ingress Controller in the cluster.  \u4f46\u90e8\u7f72\u4e0d\u4e00\u5b9a\u300c\u5b89\u88c5\u300d\uff0c\u540c\u6837\uff0c\u300c\u5b89\u88c5\u300d\u4e0d\u4e00\u5b9a\u9700\u8981\u300c\u90e8\u7f72\u300d\uff0c\u56e0\u6b64\u4ee5\u4e0b\u4f8b\u5b50\u4e0d\u80fd\u4e92\u6362\uff1a\n Deploy the API key authentication for Subscan.  Set up\uff1a\u5e03\u7f6e\u3001\u914d\u7f6e \u4e0e Deploy \u7c7b\u4f3c\uff0c\u67d0\u4e9b\u60c5\u51b5\u53ef\u4ee5\u4e92\u6362\uff0c\u4f8b\u5982\uff1a\n Set up the API key authentication for Subscan.  \u4f46 Set up \u5f80\u5f80\u672a\u9690\u542b\u300c\u5b89\u88c5\u300d\u4e4b\u4e49\uff0c\u4f8b\u5982\uff1a\n Commit 1: Install Nginx Ingress Controller in the cluster.\uff08\u5148\u5b89\u88c5\uff09 Commit 2: Set up Nginx Ingress Controller. \uff08\u518d\u914d\u7f6e\uff09  Configure\uff1a\u914d\u7f6e \u4e0e Set up \u7c7b\u4f3c\uff0c\u4f46\u7edd\u65e0\u300c\u5b89\u88c5\u300d\u4e4b\u4e49\uff1b\u4f8b\u5982\uff1a\n  Configure Nginx Ingress Controller.\n  Configure the firewall rules to mitigate DDoS attacks.\n&ldquo;DDoS attacks&rdquo; \u4e3a\u975e\u4e13\u6709\u540d\u8bcd\uff0c\u4f46\u672c\u4f8b\u4e2d\u65e0\u9700\u5e26 the\uff1b\u56e0\u4e3a\u8be5\u4e0a\u4e0b\u6587\u5185\uff0c&ldquo;DDoS attacks&rdquo; \u662f\u591a\u6b21\u7684\u3001\u6cdb\u6307\u7684\u3001\u4e0d\u660e\u786e\u7684\u3001\u975e\u7279\u5b9a\u67d0\u6b21\u6216\u67d0\u51e0\u6b21\u7684\u3002\n  Set\uff1a\u8bbe\u7f6e \u4e0e Set up \u542b\u4e49\u4e0d\u540c\uff0cSet \u7c7b\u4f3c\u4e8e Change\uff1b\u4f8b\u5982\uff1a\n Set the Subscan API plan back to free for the user example@gmail.com. Set the PVC size of the Darwinia node to 100 GiB.  Improve\uff1a\u6539\u5584 \u4f8b\u5982\uff1a\n Improve the CI configuration to speed up. Improve scheduling the cron jobs.  Enhance\uff1a\u589e\u5f3a \u76f8\u6bd4\u4e8e Improve\uff0c\u901a\u5e38\u6307\uff08\u8f83\u5c0f\u7684\uff09\u6539\u8fdb\uff1b\u4f8b\u5982\uff1a\n Enhance the CI scripts. Enhance the detecting algorithm.  Refactor\uff1a\u91cd\u6784 \u76f8\u6bd4\u4e8e Improve\uff0c\u901a\u5e38\u6307\u8f83\u5927\u8303\u56f4\u7684\u91cd\u6784\uff1b\u4f8b\u5982\uff1a\n Refactor the CI\/CD system. Refactor watching Darwinia chain events.\uff08\u975e\u4e13\u6709\u540d\u8bcd\u4e0d\u5e26 the \u7684\u53e6\u4e00\u4f8b\u5b50\uff09  Optimize\uff1a\u4f18\u5316\uff08\u6027\u80fd\uff09 \u4e0e Improve \u7c7b\u4f3c\uff0c\u4f46\u5f80\u5f80\u7279\u6307\u6027\u80fd\u3001\u6210\u672c\u4f18\u5316\uff0c\u4f7f\u67d0\u7269\u80fd\u88ab\u66f4\u52a0\u5145\u5206\u5730\u5229\u7528\uff1b\u4f8b\u5982 Improve \u7684\u4f8b\u5b50\uff1a\n Improve the CI configuration to speed up. \u53ef\u7b49\u6548\u66ff\u6362\u4e3a\uff1aOptimize the CI configuration.  Tune\uff1a\u8c03\u6574\u3001\u8c03\u8282 \u4e0e Improve \u7c7b\u4f3c\uff0c\u4f46\u5f80\u5f80\u4e0d\u76f4\u63a5\u8868\u793a\u300c\u6539\u5584\u300d\u4e4b\u4e49\uff0c\u800c\u662f\u4e3a\u4e86\u8fbe\u6210\u67d0\u4e2a\u6548\u679c\uff08\u6709\u53ef\u80fd\u662f\u6539\u5584\uff09\uff0c\u8c03\u6574\u3001\u8c03\u8282\u53c2\u6570\uff1b\u4f8b\u5982\uff1a\n Tune the Nginx parameters to allow more connections. Tune MySQL&rsquo;s configuration for long queries.  Organize\uff1a\u6574\u7406 \u4e0e Improve \u7c7b\u4f3c\uff0c\u4f46\u5f80\u5f80\u7279\u6307\u7ec4\u7ec7\u3001\u5b89\u6392\u3001\u6574\u7406\uff1b\u4f8b\u5982\uff1a\n Organize the list of Subscan API keys. Organize the YAML files into separated directories.  Remove\uff1a\u79fb\u9664\u3001\u5378\u8f7d \u4f8b\u5982\uff1a\n Remove Nginx Ingress Controller from the cluster. Remove the labels in deployment.yaml.  Deprecate\uff1a\u5e9f\u5f03 \u5f80\u5f80\u7528\u4e8e\u5e9f\u5f03\u3001\u6ce8\u91ca\u67d0\u7269\uff0c\u4f46\u6682\u4e0d\u79fb\u9664\u65f6\uff1b\u4f8b\u5982\uff1a\n Deprecate the Ingress API version v1beta1. Deprecate the Helm-flavor deployments. ","permalink":"https:\/\/wi1dcard.dev\/posts\/verbs-in-git-commit-messages-and-changelogs\/","summary":"<p>\u4f18\u8d28\u7684 Git commit message \u548c Changelog \u4e0d\u4ec5\u53ef\u4ee5\u8ba9\u534f\u4f5c\u8005\u4eec\u4e00\u76ee\u4e86\u7136\u5730\u4e86\u89e3\u7248\u672c\u53d8\u66f4\uff0c\u66f4\u80fd\u5e2e\u52a9\u4f60\u5feb\u901f\u56de\u5fc6\u66fe\u7ecf\u7684\u4fee\u6539\u3002\u56e0\u6b64\uff0c\u5408\u7406\u5730\u4f7f\u7528\u82f1\u8bed\u52a8\u8bcd\u3001\u901a\u8fc7\u300c\u4e00\u53e5\u8bdd\u300d\u7cbe\u51c6\u5730\u6982\u62ec\u505a\u4e86\u4ec0\u4e48\u4e8b\u3001\u7f16\u5199\u6613\u8bfb\u6613\u61c2\u7684\u63cf\u8ff0\u5c31\u663e\u5f97\u5c24\u4e3a\u91cd\u8981\u3002\u672c\u6587\u76ee\u7684\u662f\u7d22\u5f15\u548c\u603b\u7ed3\u5e38\u7528\u7684\u52a8\u8bcd\u5217\u8868\uff0c\u5185\u5bb9\u4ec5\u51ed\u6211\u4e2a\u4eba\u7ecf\u9a8c\u4ee5\u53ca\u6709\u9650\u7684\u67e5\u9605\u8d44\u6599\uff0c\u8bf7\u7ed3\u5408\u5b9e\u9645\u60c5\u51b5\u4f7f\u7528\u3002<\/p>","title":"Git Commit Messages \u548c Changelog \u4e2d\u7684\u5e38\u7528\u52a8\u8bcd\u53c2\u8003"},{"content":"Polkadot and other Substrate-based chain nodes supports JSON RPC over HTTP and over WebSocket on ports 9933 and 9944 individually.\nHowever, according to the WebSocket handshake, we can determine if the client is requesting WebSocket or other HTTP resource by the header Upgrade: websocket.\nHere&rsquo;s a little trick in Nginx to reverse proxy both 9933 (HTTP) and 9944 (WebSocket) with the same host, same port, and same path \/ location.\nmap $http_upgrade $upstream_backend { # proxy to 9944 if the client wanted to upgrade to a websocket conn websocket http:\/\/127.0.0.1:9944; # proxy to 9333 otherwise default http:\/\/127.0.0.1:9933; } server { listen 80 default_server; listen [::]:80 default_server; server_name _; location \/ { proxy_pass $upstream_backend; } } ","permalink":"https:\/\/wi1dcard.dev\/posts\/serve-http-and-websocket-with-the-same-port-path-in-nginx\/","summary":"<p>Polkadot and other Substrate-based chain nodes supports JSON RPC <strong>over HTTP<\/strong> and <strong>over WebSocket<\/strong> on ports 9933 and 9944 individually.<\/p>\n<p>However, according to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebSocket#Protocol_handshake\" target=\"_blank\">WebSocket handshake<\/a>, we can determine if the client is requesting WebSocket or other HTTP resource by the header <code>Upgrade: websocket<\/code>.<\/p>\n<p>Here&rsquo;s a little trick in Nginx to reverse proxy both 9933 (HTTP) and 9944 (WebSocket) with the same host, same port, and same path \/ location.<\/p>","title":"Serve HTTP and WebSocket with the Same Port and Path in Nginx"},{"content":"Kube-prometheus provides quite a few great collections of components and alerts that help us monitoring our Kubernetes cluster. I&rsquo;ve used it in the production cluster for serveral months. Although the project exposes a bunch of options via _config+:: to makes it partially configurable, the scope of parameters that we can modify is still limited.\nThe Real-life Problems For example, we currently deploy our workloads on Google Kubernetes Engine (a.k.a. GKE) on Google Cloud Platform. GKE hosts the master node of the cluster, which could mean some components such as the scheduler and controller manager are &ldquo;invisible&rdquo; to users.\nTherefore, the alert rule groups kube-scheduler.rules, kubernetes-system-scheduler, and kubernetes-system-controller-manager is unnecessary for us, as well as some Grafana dashboards. I personnally want to remove them to prevent potential confusion.\nAnother example would be editing the for field of alert rules. The default threshold of alert KubePodNotReady is 15m. This is a bit too long for our SLA. We want a shorter duration that we can tolerate.\nSolutions The good news is, credit to the powerful Jsonnet syntax, we have the ability to customize and tinker the project without forking or copy-pasting.\nTl;DR:\n\/\/ \/\/ Part One \/\/ local prometheusRuleManipulators = [ function(rule) if !std.objectHas(rule, &quot;alert&quot;) || rule.alert != &quot;KubePodNotReady&quot; then \/\/ Skip other rules rule else rule + { 'for': '5m', \/\/ Shorten the duration annotations+: { \/\/ Update durations in the description at the same time description: std.strReplace(super.description, &quot;15 minutes&quot;, &quot;5 minutes&quot;), }, }, function(rule) rule, \/\/ Do whatever you want \/\/ Add more functions in the array to customize rules ]; \/\/ \/\/ Part Two \/\/ local applyRuleManipulators(rule, idx) = if !std.objectHas(rule, &quot;alert&quot;) then \/\/ Don't apply to record rules rule else if idx &gt;= std.length(prometheusRuleManipulators) then \/\/ Exit the recursion rule else local f = prometheusRuleManipulators[idx]; local r = f(rule); applyRuleManipulators(r, idx + 1); \/\/ \/\/ Part Three \/\/ local manipulatePrometheusRules(rules) = [ applyRuleManipulators(rule, 0) for rule in rules \/\/ Add optional `if` to filter rules like below ]; local manipulatePrometheusGroups(groups) = [ group + { rules: manipulatePrometheusRules(group.rules) } for group in groups if !std.member([ \/\/ Filter and remove some rule groups 'kube-scheduler.rules', 'kubernetes-system-scheduler', 'kubernetes-system-controller-manager', ], group.name) ]; local kp = (import 'kube-prometheus\/kube-prometheus.libsonnet') + { prometheusAlerts+:: { groups: manipulatePrometheusGroups(super.groups) }, }; \/\/ ... Part One: prometheusRuleManipulators As you can see, my idea was to define a bunch of &ldquo;manipulators&rdquo; in an array (prometheusRuleManipulators). Like middlewares in the web apps development, all HTTP requests pass through middlewares serially and can be changed before it arrives the app, I want all alerts to be sent to the manipulators and save the outputs of the last manipulator as the final results.\nPart Two: applyRuleManipulators I initally tended to implement this using for:\n\/\/ Won't work for fn in manipulators alert = fn(alert) \/\/ Won't work either local alert = fn(alert) for fn in manipulators However, Jsonnet seemed not allowing that. So I ended up using a recursion in applyRuleManipulators. It calls the function in prometheusRuleManipulators[idx], increments idx by one, then calls itself with a larger idx, until idx &gt;= std.length(prometheusRuleManipulators).\nPart Three I made 2 functions manipulatePrometheusGroups and manipulatePrometheusRules, which traverse the groups and rules respectively, and optionally filter out ones that we don&rsquo;t utilize with the Python-style for and if.\nThe function manipulatePrometheusRules also calls applyRuleManipulators mentioned above to apply manipulators.\nFinally, we can override the alerts by calling manipulatePrometheusGroups(super.groups) at the end.\nRead More I also found a way to edit the alerts using std.map after I&rsquo;ve made this: https:\/\/github.com\/prometheus-operator\/kube-prometheus\/discussions\/607. And a great quick-start tutorial of Jsonnet in Chinese: https:\/\/archive.li\/IWlZG, https:\/\/archive.li\/L4k1L.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/customize-kube-prometheus-built-in-alerts\/","summary":"<p><a href=\"https:\/\/github.com\/prometheus-operator\/kube-prometheus\" target=\"_blank\">Kube-prometheus<\/a> provides quite a few great collections of components and alerts that help us monitoring our Kubernetes cluster. I&rsquo;ve used it in the production cluster for serveral months. Although the project exposes a bunch of options via <code>_config+::<\/code> to makes it partially configurable, the scope of parameters that we can modify is still limited.<\/p>","title":"Customize Kube-Prometheus Built-in Alerts"},{"content":"\u8bb0\u5f97\u53bb\u5e74\u5199\u8fc7\u4e00\u7bc7 \u4e00\u7bc7\u53c8\u957f\u53c8\u4e4f\u5473\u7684\u5e74\u7ec8\u603b\u7ed3\u548c\u5c55\u671b\uff0c\u867d\u7136\u73b0\u5728\u5df2\u7ecf\u662f 2021 \u5e74\u7684 2 \u6708\u4e86\uff0c\u518d\u6765\u56de\u987e\u7a0d\u5fae\u665a\u4e86\u4e9b\uff0c\u4e0d\u8fc7\u6211\u8fd8\u662f\u51b3\u5b9a\u603b\u7ed3\u4e00\u4e0b\u53bb\u5e74\uff0c\u518d\u7ed9\u65b0\u4e00\u5e74\u5236\u5b9a\u51e0\u4e2a\u957f\u671f\u76ee\u6807\u3002\n2020 \u56de\u987e\u548c\u5e74\u521d\u76ee\u6807 \u6211\u53bb\u5e74\u7ed9\u81ea\u5df1\u5b9a\u7684\u76ee\u6807\u5982\u4e0b\uff1a\n \u4fdd\u8bc1\u8eab\u4f53\u5065\u5eb7 \u2014\u2014 \u8fbe\u6210\uff01\uff08\u7b97\u662f\uff1f\uff09 \u5feb\u901f\u5c06\u79d1\u5b66\u4e0a\u7f51\u76f8\u5173\u5185\u5bb9\u6536\u5c3e\uff0c\u8fdb\u5165\u7ef4\u62a4\u9636\u6bb5\uff0c\u4e0d\u518d\u5360\u7528\u5927\u91cf\u65f6\u95f4\u7ee7\u7eed\u5f00\u53d1 \u2014\u2014 \u8fbe\u6210\uff01\u81ea\u8c6a\u5730\u8fbe\u6210\uff01 \u6df1\u5165\u5b66\u4e60 Kubernetes\uff0c\u5305\u62ec\u76ee\u524d\u6682\u65f6\u4e0d\u719f\u6089\u7684\uff1a  Taint\u3001Tolerations\u3001Node Affinity\u3001Autoscaler\u3001Resource Request \u7b49\u7279\u6027 \u2014\u2014 \u8fbe\u6210\uff01 HorizontalPodAutoscaler\u3001PodSecurityPolicy\u3001NetworkPolicy\u3001LimitRange \u7b49\u8d44\u6e90 \u2014\u2014 \u57fa\u672c\u8fbe\u6210\uff01\u8fd8\u9700\u8981\u7ee7\u7eed\u5de9\u56fa\u3002 \u4ee5\u53ca\u4e89\u53d6\u80fd\u5bf9 CRI\/CSI\/CNI\u3001Scheduler \u7b49 Kubernetes \u5185\u90e8\u539f\u7406\u6709\u4e00\u5b9a\u4e86\u89e3 \u2014\u2014 \u989d\u5916\u76ee\u6807\uff0c\u672a\u8fbe\u6210\uff0c\u7f3a\u4e4f\u5408\u9002\u7684\u673a\u4f1a\u3002   \u7ee7\u7eed\u953b\u70bc\u82f1\u8bed\uff0c\u5305\u62ec\uff1a  \u5c3d\u53ef\u80fd\u591a\u53c2\u4e0e\u90ae\u4ef6\u548c Slack \u8ba8\u8bba \u2014\u2014 \u8d85\u989d\u8fbe\u6210\uff01 \u575a\u6301\u7528\u82f1\u6587\u7f16\u5199\u6280\u672f\u5411\u535a\u6587 \u2014\u2014 \u8fbe\u6210\uff01 \u4ee5\u53ca\u4e89\u53d6\u7ec3\u4e60\u51e0\u6b21 italki \u2014\u2014 \u8d85\u8d85\u8d85\u989d\u8fbe\u6210\uff01   \u6df1\u5165\u5b66\u4e60 Prometheus\uff0c\u638c\u63e1\uff1a  PromQL \u8fdb\u9636\u8bed\u6cd5 \u2014\u2014 \u8fbe\u6210\uff01 \u901a\u8fc7 Prometheus Operator \u548c Custom Metrics \u5bf9 Kubernetes \u96c6\u7fa4\u76d1\u63a7 \u2014\u2014 \u8fbe\u6210\uff01 \u4ee5\u53ca\u63d0\u5347 Golang \u7f16\u7801\u6c34\u5e73\uff0c\u4e89\u53d6\u5199\u4e00\u4e2a Prometheus Exporter \u5e76\u5f00\u6e90 \u2014\u2014 \u8fbe\u6210\uff01    \u7406\u60f3\u65f6\u95f4\u5206\u914d\u4e0e\u5b9e\u9645\u60c5\u51b5\u57fa\u672c\u4e00\u81f4\uff1a\nKubernetes 4 : \u82f1\u8bed 2 : Golang 1.5 : Prometheus 1 : \u79d1\u5b66\u4e0a\u7f51 1 : \u5176\u5b83 0.5\n\u975e\u5e38\u68d2\uff01\n\u5176\u5b9e\u6700\u8ba9\u6211\u5174\u594b\u7684\u4e0d\u662f\u6280\u672f\u65b9\u9762\uff0c\u800c\u662f OOPT \u7684\u6210\u7ee9\u4ece B2 \u63d0\u5347\u5230\u4e86 C1\uff08\u603b\u5206 80\uff09\uff0c\u4e00\u5e74\u7684\u52aa\u529b\u548c\u575a\u6301\u89c1\u5230\u4e86\u56de\u62a5\uff0c\u8650\u7206\u5e74\u521d\u7684\u76ee\u6807\u3002\n2021 \u5c55\u671b\u548c\u76ee\u6807  \u5f53\u7136\u5566\uff0c\u8eab\u4f53\u5065\u5eb7\u3001\u5fc3\u60c5\u6109\u5feb\u3002 \u7ee7\u7eed\u6df1\u5165 Kubernetes\uff0c\u4e89\u53d6\u5199\u4e00\u4e2a Operator \u5e76\u5f00\u6e90\u3002 \u7ee7\u7eed\u953b\u70bc\u82f1\u8bed\uff0c\u4e89\u53d6\u5b9e\u73b0 OOPT \u603b\u5206 90\u3001Use of English \u5355\u9879 C1\u3002 \u9002\u5f53\u4e86\u89e3\u52a0\u5bc6\u8d27\u5e01\u548c Substrate \u76f8\u5173\u77e5\u8bc6\u3002 \u957f\u671f\u65c5\u884c\u4e00\u6b21\uff01  \u548c 2020 \u5e74\u76ee\u6807\u4e00\u5bf9\u6bd4\uff0c2021 \u5e74\u7684\u6211\u4f3c\u4e4e\u597d\u54b8\u9c7c\u5440\uff0c\u770b\u8d77\u6765\u8981\u8fc7\u4e00\u4e2a\u95f4\u9694\u5e74\u7684\u6837\u5b50\uff1f\u4e0d\u8fc7\u8fd9\u4e5f\u6b63\u7b26\u5408\u6211\u7684\u5e74\u7eaa\uff0c\u6ca1\u6bdb\u75c5\u3002\nhttps:\/\/www.youtube.com\/watch?v=nNe4RUHpLWI\n\u5c3d\u7ba1\u67d0\u4e9b\u7231\u597d\u548c\u751f\u6d3b\u65b9\u5f0f\u53ef\u80fd\u4e0d\u4f1a\u662f\u6211\u4e00\u76f4\u559c\u6b22\u7684\uff0c\u4f46\u4eba\u751f\u5c31\u662f\u8981\u5145\u6ee1\u4f53\u9a8c\uff0c\u4e0d\u662f\u4e48\u3002\n\u52a0\u6cb9\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/hello-2021\/","summary":"<p>\u8bb0\u5f97\u53bb\u5e74\u5199\u8fc7\u4e00\u7bc7 <a href=\"\/posts\/hello-2020\/\">\u4e00\u7bc7\u53c8\u957f\u53c8\u4e4f\u5473\u7684\u5e74\u7ec8\u603b\u7ed3\u548c\u5c55\u671b<\/a>\uff0c\u867d\u7136\u73b0\u5728\u5df2\u7ecf\u662f 2021 \u5e74\u7684 2 \u6708\u4e86\uff0c\u518d\u6765\u56de\u987e\u7a0d\u5fae\u665a\u4e86\u4e9b\uff0c\u4e0d\u8fc7\u6211\u8fd8\u662f\u51b3\u5b9a\u603b\u7ed3\u4e00\u4e0b\u53bb\u5e74\uff0c\u518d\u7ed9\u65b0\u4e00\u5e74\u5236\u5b9a\u51e0\u4e2a\u957f\u671f\u76ee\u6807\u3002<\/p>","title":"\u4e00\u7bc7\u4e0d\u957f\u4f46\u4f3c\u4e4e\u8fd8\u662f\u6709\u70b9\u4e4f\u5473\u7684\u5e74\u7ec8\u603b\u7ed3"},{"content":"\u8fd9\u7bc7\u535a\u5ba2\u4e00\u6539\u6211\u4e4b\u524d\u6587\u98ce\u7684\u5e38\u6001\uff0c\u56e0\u4e3a\u7f51\u4e0a\u7684\u76f8\u5173\u4e13\u4e1a\u8d44\u6599\u5df2\u7ecf\u5f88\u591a\uff0c\u6211\u5c3d\u53ef\u80fd\u4ee5\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u6765\u4ecb\u7ecd\uff0c\u653e\u5f03\u4e86\u90e8\u5206\u4e13\u4e1a\u6027\uff0c\u671b\u8bfb\u8005\u89c1\u8c05\u3002\n\u6211\u4eec\u5148\u6765\u8c08\u8c08\u300c\u9632\u6b62\u653b\u51fb\u8005\u4f2a\u9020\u6211\u4eec\u5411\u5176\u4ed6\u4eba\u53d1\u9001\u90ae\u4ef6\u300d\u3002\u8981\u7406\u89e3\u4e3a\u4ec0\u4e48\u4f1a\u5b58\u5728\u4f2a\u9020\u90ae\u4ef6\u4ee5\u53ca\u5982\u4f55\u9632\u6b62\u4f2a\u9020\u90ae\u4ef6\uff0c\u9996\u5148\u9700\u8981\u660e\u767d\u90ae\u4ef6\u673a\u5236\u662f\u600e\u6837\u5de5\u4f5c\u7684\u3002\n\u53d1\u9001\u90ae\u4ef6\u65f6\u53d1\u751f\u4e86\u4ec0\u4e48\uff1f \u4e3a\u4e86\u65b9\u4fbf\u7406\u89e3\uff0c\u4f60\u53ef\u4ee5\u628a\u300c\u53d1\u9001\u90ae\u4ef6\u300d\u770b\u4f5c\u662f\u7c7b\u4f3c\u63d0\u4ea4 HTTP \u8bf7\u6c42\u7684\u8fc7\u7a0b\u3002\n\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u5047\u8bbe\u6211\u4eec\u662f user@foo.com\uff0c\u7ed9 remote@bar.com \u53d1\u90ae\u4ef6\uff0c\u5728\u70b9\u51fb\u300c\u53d1\u9001\u300d\u7684\u90a3\u4e00\u523b\uff0c\u6211\u4eec\u7684\u90ae\u4ef6\u670d\u52a1\u5668\u67e5\u8be2 bar.com \u7684 MX \u8bb0\u5f55\uff0cDNS \u670d\u52a1\u5668\u8fd4\u56de 1.1.1.1\uff0c\u63a5\u7740\u6211\u4eec\u7684\u90ae\u4ef6\u670d\u52a1\u5668\u4e0e\u5bf9\u65b9 1.1.1.1 \u5efa\u7acb TCP \u94fe\u63a5\uff0c\u53d1\u9001\u4ee5\u4e0b\u5185\u5bb9\uff08\u4ec5\u4f9b\u7406\u89e3\u6982\u5ff5\uff0c\u4e0e\u771f\u5b9e\u60c5\u51b5\u4e0d\u540c\uff09\uff1a\n\u4f60\u597d\uff0c\u6211\u662f &lt;user@foo.com&gt; \u6211\u6709\u90ae\u4ef6\u7ed9 &lt;remote@bar.com&gt; \u6807\u9898\u662f xxxx \u5185\u5bb9\u662f yyyy \u4e8e\u662f\u6211\u4eec\u7684\u90ae\u4ef6\u5c31\u5230\u8fbe\u4e86 remote@bar.com \u7684\u90ae\u4ef6\u670d\u52a1\u5668\uff0c\u670d\u52a1\u5668\u8bb0\u5f55\u5e76\u5b58\u50a8\u5230\u6536\u4ef6\u7bb1\u4f9b\u5bf9\u65b9\u67e5\u770b\u3002\n\u8fd9\u6574\u4e2a\u8fc7\u7a0b\u4e2d\u4e0d\u5b58\u5728\u4efb\u4f55\u5bf9\u300c\u6211\u65b9\u300d\u7684\u8eab\u4efd\u9a8c\u8bc1\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u4efb\u4f55\u4eba\u53ef\u4ee5\u94fe\u63a5\u5230 remote@bar.com \u7684\u90ae\u4ef6\u670d\u52a1\u5668\uff0c\u8bf4\uff1a\u6211\u662f &lt;user@foo.com&gt;\uff0c\u6211\u6709\u90ae\u4ef6\u7ed9 xxxx\u3002\u8fd9\u5c31\u7ed9\u4e86\u653b\u51fb\u8005\u4f2a\u88c5\u6210\u300c\u6211\u65b9\u300d\u7684\u53ef\u80fd\u6027\u3002\nSPF \u600e\u4e48\u529e\u5462\uff1f\u4e8e\u662f SPF \u88ab\u53d1\u660e\u4e86\u3002SPF \u673a\u5236\u8981\u6c42\u6211\u4eec\uff0c\u5728\u9700\u8981\u53d1\u9001\u90ae\u4ef6\u7684\u57df\u540d\u4e0b\uff08foo.com\uff09\uff0c\u65b0\u589e\u4e00\u6761 SPF \u8bb0\u5f55\uff0c\u5185\u5bb9\u5927\u6982\u662f\uff08\u4ec5\u4f9b\u7406\u89e3\u6982\u5ff5\uff0c\u4e0e\u771f\u5b9e\u60c5\u51b5\u4e0d\u540c\uff09\uff1a\n\u6211\u65b9\u90ae\u4ef6\u670d\u52a1\u5668 IP \u5730\u5740\u662f = 2.2.2.2, 3.3.3.3 \u518d\u6b21\u91cd\u590d\u4e0a\u6587\u90ae\u4ef6\u53d1\u9001\u8fc7\u7a0b\uff0c\u5bf9\u65b9\u90ae\u4ef6\u670d\u52a1\u5668\u6536\u5230\u6211\u65b9\u90ae\u4ef6\uff08\u6765\u81ea foo.com\uff09\u65f6\uff0c\u5c31\u53ef\u4ee5\u67e5\u8be2 foo.com \u7684 DNS \u8bb0\u5f55\uff0c\u627e\u5230\u6211\u4eec\u63d0\u524d\u8bbe\u7f6e\u597d\u7684 SPF \u8bb0\u5f55\u3002\u540c\u65f6\uff0c\u56e0\u4e3a\u300c\u53d1\u9001\u300d\u7684\u8fc7\u7a0b\u5b9e\u9645\u4e0a\u5c31\u662f TCP \u5efa\u7acb\u94fe\u63a5\uff0c\u56e0\u6b64\u5bf9\u65b9\u670d\u52a1\u5668\u4e5f\u80fd\u591f\u5f97\u5230\u53d1\u9001\u8005\u7684\u670d\u52a1\u5668 IP\u3002\u628a \u53d1\u9001\u90ae\u4ef6\u7684\u670d\u52a1\u5668 IP \u4e0e SPF \u8bb0\u5f55\u5185\u7684 IP \u5730\u5740 \u8fdb\u884c\u5bf9\u6bd4\uff0c\u5982\u679c\u4e0d\u5339\u914d\uff0c\u5219\u8ba4\u4e3a\u662f\u4f2a\u9020\u90ae\u4ef6\u3002\n\u53ef\u4ee5\u770b\u51fa\uff0c\u901a\u8fc7 SPF \u673a\u5236\uff0c\u6211\u4eec\u80fd\u8fbe\u5230\u300c\u4e0d\u662f\u4ece\u6211\u4eec\u670d\u52a1\u5668 IP \u5730\u5740\u53d1\u51fa\u7684\u90ae\u4ef6\uff0c\u88ab\u89c6\u4e3a\u5783\u573e\u90ae\u4ef6\u300d\u7684\u6548\u679c\u3002\u4f46\u662f\uff0cSPF \u5b58\u5728\u4e00\u4e9b\u5c40\u9650\u6027\uff0c\u4f8b\u5982\uff1a\n \u5047\u8bbe\u4f60\u6709\u4e24\u4e2a\u90ae\u7bb1 jane@company.com \u548c jane@personal.com\uff0c\u4f60\u7279\u522b\u70ed\u7231\u5de5\u4f5c\uff0c\u8bbe\u7f6e\u4e86\u6240\u6709\u53d1\u5230 jane@company.com \u7684\u90ae\u4ef6\u5168\u90e8\u8f6c\u5230 jane@personal.com\u3002\n\u6b64\u65f6\u4e00\u5c01\u6765\u81ea user@foo.com\uff08\u914d\u7f6e\u4e86 SPF\uff09\u7684\u90ae\u4ef6\u53d1\u9001\u5230\u4e86 jane@company.com\uff0c\u90ae\u4ef6\u670d\u52a1\u5668\u6839\u636e\u4f60\u7684\u8bbe\u7f6e\u3001\u539f\u5c01\u4e0d\u52a8\u5730 \u8f6c\u53d1\u8be5\u90ae\u4ef6\u5230 jane@personal.com\u3002\njane@personal.com \u7684\u90ae\u4ef6\u670d\u52a1\u5668\u6536\u5230\u90ae\u4ef6\u540e\uff0c\u5f00\u59cb\u6838\u5bf9 SPF \u8bb0\u5f55\u3002\u8fd9\u65f6 \u90ae\u4ef6\u7684\u53d1\u4ef6\u4eba\u4f9d\u7136\u662f user@foo.com\uff0c\u6839\u636e\u67e5\u8be2 foo.com \u7684 SPF \u914d\u7f6e\u5185\u5e76\u4e0d\u5305\u542b company.com \u90ae\u4ef6\u670d\u52a1\u5668\u7684 IP \u5730\u5740\u3002\u56e0\u6b64\u8be5\u90ae\u4ef6\u5c06\u88ab\u8bef\u5224\u4e3a\u4f2a\u9020\u90ae\u4ef6\u3002\n DKIM \u5c3d\u7ba1\u5982\u4eca\u8bb8\u591a\u90ae\u4ef6\u670d\u52a1\u5546\u5728\u81ea\u52a8\u8f6c\u53d1\u90ae\u4ef6\u65f6\uff0c\u4f1a\u4fee\u6539\u90ae\u4ef6\u7684\u53d1\u4ef6\u4eba\u6765\u89c4\u907f SPF \u89c4\u5219\u9650\u5236\u3002\u4f46\u8fd9\u5728\u7406\u8bba\u4e0a\u5e76\u4e0d\u300c\u4f18\u96c5\u300d\uff0c\u4e8e\u662f\u53c8\u8bde\u751f\u4e86 DKIM\u3002\nDKIM \u8981\u6c42\u6211\u4eec\u5728\u6211\u65b9\u90ae\u4ef6\u670d\u52a1\u5668\u5185\u751f\u6210\u4e00\u7ec4\u5bc6\u94a5\u5bf9\uff0c\u79c1\u94a5\u4fdd\u5b58\u5728\u670d\u52a1\u5668\u5185\uff0c\u516c\u94a5\u901a\u8fc7 DNS \u8bb0\u5f55\u516c\u5f00\u3002\u4e00\u6837\uff0c\u65b0\u589e\u4e00\u6761 DNS \u8bb0\u5f55\uff0c\u5185\u5bb9\u5927\u6982\u662f\uff08\u4ec5\u4f9b\u7406\u89e3\u6982\u5ff5\uff0c\u4e0e\u771f\u5b9e\u60c5\u51b5\u4e0d\u540c\uff09\uff1a\n\u6211\u65b9\u90ae\u4ef6\u7b7e\u540d\u516c\u94a5\u662f = 0xnoirh22h381uj2eoqdsjlaisud \u518d\u6b21\u91cd\u590d\u4e0a\u6587\u90ae\u4ef6\u53d1\u9001\u8fc7\u7a0b\uff0c\u4e0e SPF \u4e0d\u540c\uff0c\u6211\u65b9\u670d\u52a1\u5668\u5728\u53d1\u9001\u90ae\u4ef6\u65f6\uff0c\u9700\u8981\u5bf9\u90ae\u4ef6\u5185\u5bb9\u4f7f\u7528\u79c1\u94a5\u7b7e\u540d\uff0c\u5e76\u5c06\u7b7e\u540d\u4e0e\u90ae\u4ef6\u5185\u5bb9\u4e00\u8d77\u643a\u5e26\u7740\u53d1\u9001\u7ed9\u5bf9\u65b9\u670d\u52a1\u5668\u3002\u5bf9\u65b9\u6536\u5230\u6211\u65b9\u90ae\u4ef6\u65f6\uff08\u6765\u81ea foo.com\uff09\uff0c\u540c\u6837\u67e5\u8be2 foo.com \u7684 DNS \u8bb0\u5f55\uff0c\u62ff\u5230\u516c\u94a5\u3002\u4f7f\u7528\u516c\u94a5\u548c\u7b7e\u540d\u9a8c\u8bc1\u90ae\u4ef6\u5185\u5bb9\uff0c\u5982\u679c\u9a8c\u7b7e\u4e0d\u901a\u8fc7\uff0c\u5219\u5c06\u90ae\u4ef6\u5224\u5b9a\u4e3a\u4f2a\u9020\u3002\n\u7ed3\u5408\u4ee5\u4e0a\u4f8b\u5b50\uff08user@foo.com -&gt; jane@company.com -&gt; jane@personal.com\uff09\uff0c\u5f53 jane@company.com \u81ea\u52a8\u8f6c\u53d1\u90ae\u4ef6\u65f6\uff0c\u65e0\u9700\u4fee\u6539\u4efb\u4f55\u5b57\u6bb5\uff08\u4e5f\u4e0d\u80fd\u4fee\u6539\uff0c\u4e0d\u7136\u9a8c\u7b7e\u5c31\u4f1a\u5931\u8d25\uff09\uff0cjane@personal.com \u6536\u5230\u90ae\u4ef6\u540e\u67e5\u8be2 foo.com \u7684 DKIM \u516c\u94a5\uff0c\u9a8c\u8bc1\u90ae\u4ef6\u7b7e\u540d\u901a\u8fc7\uff0c\u5373\u53ef\u8ba4\u4e3a\u662f\u6b63\u5e38\u90ae\u4ef6\u3002\n\u5982\u6b64\u4e00\u6765\uff0c\u7ed3\u5408 DKIM \u548c SPF\uff0c\u770b\u8d77\u6765\u4e07\u4e8b\u5927\u5409\u4e86\uff1f\u5e76\u6ca1\u6709\u3002\u8ba9\u6211\u4eec\u66f4\u52a0\u6df1\u5165\u4e00\u70b9\uff0c\u770b\u4e2a\u7a0d\u5fae\u771f\u5b9e\u4e00\u70b9\u7684\u90ae\u4ef6\u3002\nReturn-Path: user@fake.com DKIM-Signature: d=fake.com, b=aldjiopurn1o23u108923jiuq123jdal From: &lt;user@foo.com&gt; To: &lt;remote@bar.com&gt; \u521a\u521a\u63d0\u5230\uff0c\u57fa\u4e8e SPF\uff0c\u6536\u4ef6\u65b9\u80fd\u591f\u5bf9\u6bd4\u300c\u53d1\u4ef6\u670d\u52a1\u5668 IP \u5730\u5740\u300d\u4e0e\u300c\u53d1\u4ef6\u4eba\u57df\u540d\u7684 SPF \u8bb0\u5f55\u5185\u7684 IP \u5730\u5740\u300d\u3002\u7136\u800c\uff0c\u56e0\u4e3a\u90ae\u4ef6\u7cfb\u7edf\u53d1\u5c55\u5386\u53f2\u4e45\u8fdc\uff0cSPF \u5b9a\u4e49\u7684\u300c\u53d1\u4ef6\u4eba\u300d\u662f RFC5321.MailFrom \u89c4\u5b9a\u7684 Return-Path\u3002DKIM \u5219\u66f4\u662f\u5728\u90ae\u4ef6\u5934\u91cc\u76f4\u63a5\u643a\u5e26\u4e86\u57df\u540d\uff08DKIM-Signature: d=\uff09\uff0c\u53ea\u8981\u4f7f\u7528\u8be5\u57df\u540d\u7684\u516c\u94a5\u9a8c\u8bc1\u901a\u8fc7\u5373\u53ef\u3002\n\u7136\u800c\uff0c\u5982\u4eca\u90ae\u4ef6\u670d\u52a1\u7ed9\u6700\u7ec8\u7528\u6237\u5c55\u793a\u7684\u300c\u53d1\u4ef6\u4eba\u300d\u51e0\u4e4e\u90fd\u662f From \u5b57\u6bb5\uff0c\u5e76\u975e SPF \u7684 Return-Path\uff0c\u4e5f\u4e0d\u662f DKIM \u7684 DKIM-Signature: d=\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u653b\u51fb\u8005\uff08fake.com\uff09\u53ef\u4ee5\u53d1\u9001\u4ee5\u4e0a\u8fd9\u5c01\u90ae\u4ef6\uff0c\u53ef\u4ee5\u5b8c\u7f8e\u901a\u8fc7 SPF \u548c DKIM \u68c0\u67e5\uff08\u56e0\u4e3a SPF \u9a8c\u8bc1\u7684 Return-Path \u662f fake.com\uff0c\u800c DKIM \u9a8c\u8bc1\u7684 d= \u4e5f\u662f fake.com\uff09\uff0c\u800c\u6700\u7ec8\u7528\u6237\u770b\u5230\u7684\u53d1\u4ef6\u4eba\u5374\u662f From \u5185\u7684 user@foo.com\u3002\u8fd9\u663e\u7136\u662f\u4e0d\u53ef\u63a5\u53d7\u7684\u3002\nDMARC \u53c8\u4e8e\u662f\uff0cDMARC \u8bde\u751f\u4e86\u3002\nDMARC \u5e76\u6ca1\u6709\u89c4\u5b9a\u5177\u4f53\u7684\u300c\u9a8c\u8bc1\u63aa\u65bd\u300d\uff0c\u800c\u662f\u57fa\u4e8e SPF \u548c DKIM\uff08\u6216\u4e8c\u8005\u4e4b\u4e00\uff09\u3002\u5b83\u89c4\u5b9a\uff0cSPF \u7684 Return-Path \u6216\u8005 DKIM \u7684 DKIM-Signature: d= \u4e8c\u8005\u81f3\u5c11\u9700\u6709\u5176\u4e00\u4e0e From \u5934\u5bf9\u5e94\uff0c\u5426\u5219\u88ab\u5224\u5b9a\u4e3a fail\u3002\u8fd9\u4e2a\u8fc7\u7a0b\u53eb\u505a Identifier Alignment\u3002\u540c\u65f6\uff0cDMARC \u8fd8\u63d0\u4f9b\u4e86\u5927\u91cf\u7684\u589e\u5f3a\u529f\u80fd\uff0c\u6bd4\u5982\u6307\u5b9a\u90a3\u4e9b fail \u7684\u90ae\u4ef6\u662f\u8fdb\u5165 Spam \u8fd8\u662f\u76f4\u63a5\u62d2\u6536\u3002\u914d\u7f6e DMARC \u7684\u65b9\u5f0f\u4e0e SPF \u548c DKIM \u7c7b\u4f3c\uff0c\u5728\u6211\u65b9\u57df\u540d DNS \u5185\u6dfb\u52a0 TXT \u8bb0\u5f55\uff0c\u5185\u5bb9\u7c7b\u4f3c\u8fd9\u6837\uff08\u4ec5\u4f9b\u7406\u89e3\u6982\u5ff5\uff0c\u4e0e\u771f\u5b9e\u60c5\u51b5\u4e0d\u540c\uff09\uff1a\n70% \u7684 fail \u90ae\u4ef6\u8fdb\u5165 Spam\uff1b \u90ae\u4ef6\u670d\u52a1\u5546\u5e94\u5f53\u5c06\u6bcf\u5929 fail \u7684\u90ae\u4ef6\u6c47\u603b\u540e\u53d1\u9001\u5230 xxx@foo.com \u4ee5\u4f9b\u5206\u6790\uff1b \u4e25\u683c\u5339\u914d\uff0c\u4e0d\u5141\u8bb8 Return-Path \u662f From \u7684\u81ea\u57df\u540d\uff1b \u5f53\u5bf9\u65b9\u90ae\u4ef6\u670d\u52a1\u5668\u6536\u5230\u90ae\u4ef6\u65f6\uff0c\u5373\u53ef\u5148\u9a8c\u8bc1 DKIM\u3001SPF\uff0c\u518d\u6839\u636e DMARC \u7684\u914d\u7f6e\uff0c\u68c0\u67e5 Identifier Alignment\u3001\u51b3\u5b9a\u5177\u4f53\u63aa\u65bd\u7b49\u3002\n\u5982\u6b64\u4e00\u6765\uff0c\u80fd\u591f\u786e\u4fdd\u6700\u7ec8\u6536\u4ef6\u4eba\u7528\u6237\u770b\u5230\u7684 From \u4e0e SPF\u3001DKIM \u8ba4\u8bc1\u7684\u53d1\u4ef6\u4eba\u4e00\u81f4\uff0c\u4e14\u7ecf\u8fc7\u4e86 SPF \u6216 DKIM \u8ba4\u8bc1\u3002\u8fd9\u6837\uff0c\u653b\u51fb\u8005\u4e5f\u5c31\u65e0\u6cd5\u4f2a\u9020\u6211\u4eec\u53d1\u51fa\u7684\u90ae\u4ef6\u4e86\u3002\n\u7ed3\u8bed \u603b\u7ed3\u4ee5\u4e0a\u8fc7\u7a0b\uff0c\u53ef\u4ee5\u770b\u51fa\uff1a\u5982\u679c\u60f3\u8981\u5f7b\u5e95\u907f\u514d\u4f2a\u9020\u90ae\u4ef6\uff0c\u662f\u9700\u8981\u6536\u53d1\u53cc\u65b9\u534f\u4f5c\u7684\u8fc7\u7a0b\u3002\u9664\u4e86\u53d1\u4ef6\u65b9\u8981\u914d\u7f6e\u597d SPF \u548c DKIM \u4f9b\u6536\u4ef6\u65b9\u9a8c\u8bc1\u5916\uff0c\u6536\u4ef6\u65b9\u7684\u670d\u52a1\u5668\u4e5f\u5fc5\u987b\u652f\u6301 \u5bf9\u6536\u5230\u7684\u90ae\u4ef6\u8fdb\u884c SPF \u548c DKIM \u8ba4\u8bc1\u3002\n\u5f53\u6211\u4eec\u4f5c\u4e3a\u6536\u4ef6\u65b9\u65f6\uff0c\u80fd\u505a\u7684\u5c31\u662f\u5c3d\u53ef\u80fd\u4f7f\u7528\u652f\u6301 SPF \u548c DKIM \u7684\u90ae\u4ef6\u670d\u52a1\u5546\uff0c\u4f8b\u5982 Gmail\uff1b\u907f\u514d\u4f7f\u7528\u4e0d\u652f\u6301\u8fd9\u4e9b\u673a\u5236\u7684\u670d\u52a1\u5546\uff0c\u6bd4\u5982\uff08\u5783\u573e\uff09\u963f\u91cc\u4e91 \/ \u9489\u9489\u90ae\u7bb1\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/anti-email-spoofing-explained\/","summary":"<p>\u8fd9\u7bc7\u535a\u5ba2\u4e00\u6539\u6211\u4e4b\u524d\u6587\u98ce\u7684\u5e38\u6001\uff0c\u56e0\u4e3a\u7f51\u4e0a\u7684\u76f8\u5173\u4e13\u4e1a\u8d44\u6599\u5df2\u7ecf\u5f88\u591a\uff0c\u6211\u5c3d\u53ef\u80fd\u4ee5\u901a\u4fd7\u6613\u61c2\u7684\u8bed\u8a00\u6765\u4ecb\u7ecd\uff0c\u653e\u5f03\u4e86\u90e8\u5206\u4e13\u4e1a\u6027\uff0c\u671b\u8bfb\u8005\u89c1\u8c05\u3002<\/p>\n<p>\u6211\u4eec\u5148\u6765\u8c08\u8c08\u300c\u9632\u6b62\u653b\u51fb\u8005\u4f2a\u9020\u6211\u4eec\u5411\u5176\u4ed6\u4eba\u53d1\u9001\u90ae\u4ef6\u300d\u3002\u8981\u7406\u89e3\u4e3a\u4ec0\u4e48\u4f1a\u5b58\u5728\u4f2a\u9020\u90ae\u4ef6\u4ee5\u53ca\u5982\u4f55\u9632\u6b62\u4f2a\u9020\u90ae\u4ef6\uff0c\u9996\u5148\u9700\u8981\u660e\u767d\u90ae\u4ef6\u673a\u5236\u662f\u600e\u6837\u5de5\u4f5c\u7684\u3002<\/p>","title":"\u901a\u4fd7\u89e3\u91ca\u53cd\u4f2a\u9020\u90ae\u4ef6\u673a\u5236 SPF\u3001DKIM \u548c DMARC"},{"content":"2020 \u5e74\u8f6c\u773c\u7ed3\u675f\u4e86\uff0c\u672c\u60f3\u5199\u5e74\u7ec8\u603b\u7ed3\u548c\u65b0\u5e74\u8ba1\u5212\uff0c\u5374\u53d1\u73b0 2020 \u5e74\u9664\u4e86\u6280\u672f\u8fdb\u6b65\uff0c\u8fd8\u603b\u7ed3\u4e86\u4e0d\u5c11\u6211\u81ea\u5df1\u7684\u300c\u5de5\u4f5c\u6280\u5de7\u300d\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u53eb\u505a\u300c\u5de5\u4f5c\u5b88\u5219\u300d\u3002\u6211\u9075\u5faa\u7740\u8fd9\u4e9b\u5b9e\u8df5\u4e2d\u603b\u7ed3\u51fa\u6765\u7684\u65b9\u6cd5\u5de5\u4f5c\uff0c\u4e3a\u6211\u81ea\u5df1\u4ee5\u53ca\u6211\u6240\u5728\u7684\u5c97\u4f4d\uff0c\u5e26\u6765\u4e86\u4e0d\u5c0f\u7684\u65f6\u95f4\u6548\u76ca\u548c\u7ecf\u6d4e\u6548\u76ca\u3002\n\u5f53\u7136\uff0c\u9002\u5408\u81ea\u5df1\u7684\u624d\u662f\u6700\u597d\u7684\uff0c\u6211\u4e0d\u559c\u6b22\u4e00\u5473\u6a21\u4eff\u5176\u5b83\u4eba\uff0c\u5e0c\u671b\u4f60\u4e5f\u5e26\u7740\u8fd9\u79cd\u60f3\u6cd5\u8bfb\u8fd9\u7bc7\u535a\u5ba2\u3002\n\u6ca1\u6709\u56fa\u5b9a\u7684\u8ba1\u5212\uff0c\u53ea\u6709 Todo\u3001Doing \u548c Done \u6709\u4e0d\u5c11\u4eba\u66fe\u5411\u6211\u63a8\u8350\u65f6\u95f4\u89c4\u5212 \u2014 \u8ba1\u5212\u6bcf\u5929\u6bcf\u6bb5\u65f6\u95f4\u5e94\u8be5\u505a\u4ec0\u4e48\u3002\u5c1d\u8bd5\u8fc7\u540e\u53d1\u73b0\u5176\u5b9e\u4e0d\u9002\u5408\u6211\u3002\u76f8\u8f83\u4e8e\u7814\u53d1\u3001\u79d1\u7814\u5c97\u4f4d\u901a\u5e38\u4f1a\u5236\u5b9a\u957f\u671f\u7684\u5f00\u53d1\u76ee\u6807\u3001\u8bba\u6587\u76ee\u6807\uff1b\u4f5c\u4e3a\u4e00\u540d DevOps \u5de5\u7a0b\u5e08\uff0c\u65e5\u5e38\u5de5\u4f5c\u66f4\u591a\u65f6\u5019\u662f\u5728\u4e0d\u65ad\u5730\u53d1\u73b0\u95ee\u9898\u548c\u89e3\u51b3\u95ee\u9898\u3002\n\u56e0\u6b64\uff0c\u6211\u66f4\u503e\u5411\u4e8e\u628a\u5f85\u529e\u4e8b\u9879\u62c6\u5206\u6210 Tickets\uff0c\u5e76\u4f7f\u7528 Kanban \u7ba1\u7406\u5b83\u4eec\u3002\u6211\u7684 Kanban \u5185\u901a\u5e38\u5305\u542b\u51e0\u5217\uff1a\n LONG TERM\uff1a\u4e0d\u7d27\u6025\u7684\u3001\u53ef\u4ee5\u672a\u6765\u518d\u505a\u7684\u4efb\u52a1\u3002\u901a\u5e38\u6765\u6e90\u662f\u5728\u5de5\u4f5c\u4e2d\u53d1\u73b0\u7684\u53ef\u4f18\u5316\u9879\uff0c\u6216\u662f\u6765\u81ea\u540c\u4e8b\u7684\u9700\u6c42\u4f46\u8c03\u7814\u540e\u53d1\u73b0\u6682\u65f6\u4e0d\u592a\u5bb9\u6613\u89e3\u51b3\u7684\u4e8b\u3002 TODO\uff1a\u9700\u8981\u5c3d\u5feb\u5b8c\u6210\u7684\u4efb\u52a1\u3002\u901a\u5e38\u6765\u6e90\u662f\u6bd4\u8f83\u91cd\u8981\u3001\u7d27\u6025\u7684\u9700\u6c42\u3002 DOING\uff1a\u6b63\u5728\u505a\u7684\u4e8b\u3002 STALLED\uff1a\u7531\u4e8e\u5916\u90e8\u56e0\u7d20\u6682\u505c\u7684\u4efb\u52a1\u3002\u6bd4\u5982\u9700\u8981\u7b49\u5f85\u67d0\u4e2a PR \u5408\u5e76\u3001\u7b49\u5f85\u540c\u4e8b\u7684\u786e\u8ba4\u56de\u590d\u7b49\u3002 DONE\uff1a\u5df2\u5b8c\u6210\u7684\u4efb\u52a1\u3002  \u6709\u4e86 Kanban\uff0c\u6211\u7684\u5de5\u4f5c\u6d41\u5c31\u6e05\u6670\u4e86\uff1a\n\u5f53\u65b0\u9700\u6c42\u51fa\u73b0\u65f6\uff0c\u6211\u4f1a\u67e5\u770b\u73b0\u5728\u7684 TODO \u548c LONG TERM \u6709\u6ca1\u6709\u7c7b\u4f3c\u7684\u4e8b\uff1b\u5982\u679c\u9700\u8981\u670d\u52a1\u4e0b\u7ebf\u7ef4\u62a4\uff0c\u6211\u4f1a\u67e5\u627e\u662f\u5426\u6709\u53ef\u4ee5\u4e00\u5e76\u5728\u540c\u4e00\u6b21\u7ef4\u62a4\u4e2d\u5b8c\u6210\u7684\u4efb\u52a1\uff0c\u5c3d\u53ef\u80fd\u51cf\u5c11\u4e0b\u7ebf\u6b21\u6570\u3002\n\u5f00\u59cb\u5de5\u4f5c\u524d\uff0c\u6211\u4f1a\u6d4f\u89c8\u4e00\u904d TODO \u548c LONG TERM\uff0c\u6839\u636e\u4efb\u52a1\u7684\u91cd\u8981\u548c\u7d27\u6025\u7a0b\u5ea6\uff0c\u8c03\u6574\u5b83\u4eec\u7684\u5148\u540e\u987a\u5e8f\u3001\u4f18\u5148\u7ea7\u7b49\uff1b\u56e0\u4e3a\u5728\u5b9e\u9645\u5de5\u4f5c\u8fc7\u7a0b\u4e2d\uff0c\u5f88\u591a\u4efb\u52a1\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u3001\u6280\u672f\u8fed\u4ee3\u3001\u5e02\u573a\u548c\u4ea7\u54c1\u8ba1\u5212\u8c03\u6574\uff0c\u53ef\u80fd\u77ac\u95f4\u4ece LONG TERM \u4e0a\u5347\u4e3a\u8f83\u7d27\u6025\uff0c\u4e5f\u53ef\u80fd\u4ece TODO \u76f4\u63a5\u6d88\u5931\uff0c\u88ab Archive\u3002\n\u6211\u8fd8\u4f1a\u65f6\u4e0d\u65f6\u770b\u770b STALLED\uff0c\u8fd9\u4e00\u5217\u80fd\u5e2e\u52a9\u6211\u7ba1\u7406\u548c\u63a8\u52a8\u90a3\u4e9b\u53d7\u5230\u5916\u90e8\u56e0\u7d20\u5f71\u54cd\u800c\u4e0d\u80fd\u7acb\u523b\u5b8c\u6210\u7684\u4efb\u52a1\uff0c\u8b6c\u5982\u7b49\u5f85\u5f00\u6e90\u9879\u76ee\u7684 Bugfix PR \u5408\u5e76\uff0c\u7b49\u5f85\u540c\u4e8b\u7684\u7b54\u590d\u4e4b\u7c7b\uff1b\u8fd9\u6837\uff0c\u6211\u53ef\u4ee5\u5b9a\u671f\u53bb PR \u50ac\u4e00\u4e0b\u5408\u5e76\u3001\u63d0\u9192\u4e00\u4e0b\u540c\u4e8b\uff0c\u8fdb\u800c\u63a8\u52a8\u300c\u5916\u90e8\u529b\u91cf\u300d\u5c3d\u5feb\u89e3\u51b3\u95ee\u9898\uff0c\u907f\u514d\u6211\u7684\u4efb\u52a1\u957f\u671f\u7531\u4e8e\u5916\u90e8\u539f\u56e0\u62d6\u5ef6\u3002\n\u6700\u540e\uff0c\u5f53\u6211\u8ba4\u4e3a\u67d0\u4e2a\u4e8b\u9879\u662f DONE\uff0c\u90a3\u4e48\u5b83\u4e00\u5b9a\u662f\u4ee5\u4e0b\u4e09\u79cd\u72b6\u6001\u4e4b\u4e00\uff1a\n \u5df2\u8fbe\u6210\u6700\u521d\u76ee\u7684\u3001\u89e3\u51b3\u4e86\u95ee\u9898\uff1b\u6216 \u672a\u89e3\u51b3\u95ee\u9898\u4f46\u51c6\u5907\u4e86\u53ef\u884c\u7684\u6298\u4e2d\u65b9\u6848\uff1b\u6216 \u65e0\u6cd5\u89e3\u51b3\u95ee\u9898\uff0c\u5e76\u7ed9\u51fa\u8bbe\u60f3\u65b9\u6848\u4ee5\u53ca\u4e0d\u53ef\u884c\u7684\u7406\u7531\u3002  \u9047\u5230\u95ee\u9898\u8981\u8bb2\uff0c\u4e3b\u52a8\u6c9f\u901a\u5e76\u6301\u7eed\u8ddf\u8fdb \u5de5\u4f5c\u8fc7\u7a0b\u4e2d\u9047\u5230\u4e0d\u719f\u6089\u7684\u5185\u5bb9\u5f88\u5e38\u89c1\u3002\u5728\u7740\u624b\u65b0\u4e8b\u9879\u7684\u7b2c\u4e00\u65f6\u95f4\uff0c\u6211\u53ef\u80fd\u4f1a\u6709\u5927\u91cf\u7684\u7591\u95ee\u3002\u8fd9\u4e9b\u7591\u95ee\u5927\u591a\u662f\u6211\u5728\u6784\u60f3\u63a5\u4e0b\u6765\u5e94\u8be5\u600e\u4e48\u505a\u65f6\uff0c\u7ed3\u5408\u7c7b\u4f3c\u4e8b\u9879\u7684\u7ecf\u9a8c\u548c\u7ecf\u5386\uff0c\u63d0\u524d\u9884\u671f\u5230\u7684\u3002\u5728\u5f00\u59cb\u505a\u4e4b\u524d\u6211\u4f1a\u5148\u95ee\u6e05\u695a\u8fd9\u4e9b\u95ee\u9898\uff1b\u5982\u679c\u5bf9\u65b9\u4e0d\u80fd\u53ca\u65f6\u89e3\u7b54\uff0c\u6216\u662f\u6307\u6d3e\u7ed9\u5176\u4ed6\u4eba\u89e3\u7b54\uff0c\u8981\u4e3b\u52a8\u5730\u6301\u7eed\u8ddf\u8fdb\u3002\u63d0\u9192\u81ea\u5df1 \u2014 \u8fd9\u4e9b\u95ee\u9898\u7684\u7b54\u6848\u6709\u52a9\u4e8e\u6211\u5de5\u4f5c\u7684\u5b8c\u6210\uff0c\u6211\u9700\u8981\u8fd9\u4e9b\u7b54\u6848\u3002\n\u5373\u65f6\u901a\u8baf\u964d\u4f4e\u4e86\u67d0\u4e9b\u573a\u666f\u4e0b\u7684\u6c9f\u901a\u6210\u672c\uff0c\u4f46\u540c\u65f6\u4e5f\u8ba9\u6309\u4e0b\u53d1\u9001\u952e\u524d\u4e00\u523b\u7684\u601d\u8003\u53d8\u5c11\u4e86\u3002\u4e3a\u4e86\u63d0\u9ad8\u8be2\u95ee\u4ed6\u4eba\u65f6\u7684\u6c9f\u901a\u6548\u7387\uff0c\u6211\u4e00\u822c\u4f1a\u9075\u5faa\u8fd9\u51e0\u4e2a\u539f\u5219\uff1a\n \u5c06\u591a\u4e2a\u5c0f\u95ee\u9898\u5408\u5e76\u6210\u4e00\u6761\u6d88\u606f\u53d1\u9001\uff0c\u907f\u514d\u5bf9\u65b9\u9057\u6f0f\u6d88\u606f\u3002 \u4f7f\u7528 1. 2. 3. \u6570\u5b57\u7f16\u53f7\uff0c\u5f53\u95ee\u9898\u4e4b\u95f4\u6709\u4f9d\u8d56\u5173\u7cfb\u65f6\u65b9\u4fbf\u5f15\u7528\uff0c\u540c\u65f6\u5bf9\u65b9\u80fd\u591f\u6839\u636e\u7f16\u53f7\u56de\u7b54\uff0c\u4e0d\u5bb9\u6613\u9057\u6f0f\u6216\u8dd1\u9898\u3002 \u53d1\u9001\u9700\u8981\u590d\u5236\u7c98\u8d34\u7684\u5185\u5bb9\u65f6\uff08\u4f8b\u5982\u62a5\u9519\u4fe1\u606f \u2014 \u53ef\u80fd\u5bf9\u65b9\u9700\u8981\u590d\u5236\u5230 Google \u5185\u641c\u7d22\uff09\uff0c\u4e0d\u8981\u622a\u56fe\uff1b\u540c\u65f6\u5c3d\u53ef\u80fd\u4f7f\u7528\u4ee3\u7801\u683c\u5f0f\uff0c\u907f\u514d\u5bf9\u65b9\u4e0d\u5c0f\u5fc3\u590d\u5236\u591a\u4f59\u7684\u5185\u5bb9\uff0c\u4e14\u80fd\u63d0\u5347\u6d88\u606f\u9605\u8bfb\u4f53\u9a8c\u3002 \u53d1\u9001\u4e4b\u524d\u5feb\u901f\u6d4f\u89c8\u4e00\u904d\u6d88\u606f\u3002\u6574\u7406\u53e5\u5b50\u7ed3\u6784\uff0c\u907f\u514d\u5197\u4f59\u7684\u8bdd\u672f\uff0c\u786e\u4fdd\u6392\u7248\u683c\u5f0f\u6b63\u786e\uff0c\u628a\u5373\u65f6\u6d88\u606f\u5f53\u4f5c\u4e00\u5c01\u5bf9\u65b9\u51e0\u5c0f\u65f6\u540e\u624d\u80fd\u56de\u590d\u7684\u90ae\u4ef6\u3002  \u4e0d\u8fdb\u884c\u6ca1\u6709\u7ed3\u679c\u7684\u8ba8\u8bba\uff0c\u8ba8\u8bba\u7ed3\u675f\u8981\u6709\u5207\u5b9e\u53ef\u884c\u7684\u300c\u4e0b\u4e00\u6b65\u300d \u5f53\u6211\u8ba4\u4e3a\u5373\u65f6\u6d88\u606f\u65e0\u6cd5\u5feb\u901f\u8ba8\u8bba\u95ee\u9898\uff0c\u6216\u662f\u6709\u8fc7\u591a\u7ec6\u8282\u9700\u8981\u300c\u5934\u8111\u98ce\u66b4\u300d\u5feb\u901f\u4ea4\u6362\u60f3\u6cd5\u65f6\uff0c\u6211\u4f1a\u53d1\u8d77\u4e00\u6b21\u8ba8\u8bba\u6216\u8005\u4f1a\u8bae\u3002\u4e3a\u4e86\u80fd\u591f\u5feb\u901f\u63a8\u52a8\u8fdb\u5ea6\uff0c\u6211\u901a\u5e38\u4f1a\u5728\u63a5\u8fd1\u4f1a\u8bae\u5c3e\u58f0\u65f6\u7b80\u5355\u603b\u7ed3\uff0c\u5927\u81f4\u7ed3\u6784\u662f\uff1a\n \u300c\u67d0\u4eba\u300d\u5e94\u5f53\u5728\u300c\u67d0\u65f6\u95f4\u5185\u300d\u5b8c\u6210\u300c\u67d0\u4e8b\u300d\uff0c\u8fc7\u7a0b\u4e2d\u53ef\u5bfb\u6c42\u300c\u67d0\u67d0\u300d\u7684\u5e2e\u52a9\u3002\n \u56e0\u6b64\uff0c\u4f1a\u8bae\u7ed3\u675f\u540e\uff0c\u53c2\u4f1a\u540c\u4e8b\u80fd\u6e05\u695a\u5730\u77e5\u9053\uff1a\u81ea\u5df1\u4e0b\u4e00\u6b65\u8981\u505a\u4ec0\u4e48\u3001\u9700\u8981\u4e0e\u8c01\u534f\u4f5c\u3001\u4ea7\u51fa\u4ec0\u4e48\u7ed3\u679c\u3002\u907f\u514d A \u4ee5\u4e3a B \u4f1a\u505a\uff0cB \u4ee5\u4e3a A \u4f1a\u505a\uff0c\u518d\u52a0\u4e0a\u53cc\u65b9\u6b20\u7f3a\u6c9f\u901a\uff0c\u7ed3\u679c\u8c01\u90fd\u6ca1\u505a\u7684\u5c34\u5c2c\u5c40\u9762\u3002\n\u660e\u786e\u6709\u65f6\u6bd4\u4f18\u96c5\u66f4\u91cd\u8981 \u4f5c\u4e3a\u7a0b\u5e8f\u5458\uff0c\u89e3\u51b3\u95ee\u9898\u7684\u8fc7\u7a0b\u4e2d\u5c11\u4e0d\u4e86\u5199\u4ee3\u7801\u3002\u867d\u7136\u6709\u4e0d\u5c11\u4eba\u575a\u6301\u4ee3\u7801\u5e94\u8be5\u4f18\u96c5\u800c\u5b8c\u7f8e\uff0c\u800c\u6211\u8ba4\u4e3a\u67d0\u4e9b\u65f6\u5019\u660e\u786e\u6bd4\u4f18\u96c5\u66f4\u91cd\u8981\u3002\u5f53\u4e24\u65b9\u51b2\u7a81\u65f6\uff0c\u6211\u9700\u8981\u6743\u8861\u5e76\u5c3d\u53ef\u80fd\u53d6\u5f97\u5e73\u8861\u3002\u4f8b\u5982\u4ee5\u4e0b\u51e0\u4e2a\u5177\u4f53\u573a\u666f\uff1a\n \u4f7f\u7528\u6700\u7b80\u5316\u7684\u9ed8\u8ba4\u503c\uff0c\u5f53\u9ed8\u8ba4\u53c2\u6570\u65e0\u6cd5\u6b63\u5e38\u8fd0\u884c\u65f6\uff0c\u901a\u8fc7\u62a5\u9519\u5f15\u5bfc\u7528\u6237\u663e\u5f0f\u5730\u8c03\u6574\u67d0\u4e2a\u503c\uff0c\u800c\u4e0d\u662f\u9690\u5f0f\u5730\u81ea\u52a8\u4fee\u6539\u9ed8\u8ba4\u503c \u2014\u2014 \u8ba9\u7528\u6237\u9010\u6e10\u719f\u6089\u914d\u7f6e\uff0c\u907f\u514d\u300c\u867d\u7136\u80fd\u8fd0\u884c\uff0c\u5374\u7559\u4e0b\u4e86\u672a\u6765\u624d\u80fd\u53d1\u73b0\u7684\u6697\u5751\u300d\u3002 \u5f53\u67d0\u4e2a\u6587\u4ef6\u4e0d\u5f97\u4e0d\u590d\u5236\u7c98\u8d34\u65f6\uff0c\u5728\u65b0\u65e7\u526f\u672c\u5404\u6dfb\u52a0\u4e00\u6bb5\u6ce8\u91ca\uff0c\u8868\u793a\u8be5\u6587\u4ef6\u5e94\u5f53\u4e0e\u53e6\u4e00\u5904\u4fdd\u6301\u540c\u6b65 \u2014\u2014 \u5f53\u672a\u6765\u7684\u6211\u6216\u5176\u4ed6\u540c\u4e8b\u63a5\u624b\u65f6\uff0c\u5c3d\u91cf\u907f\u514d\u6f5c\u5728\u7684\u95ee\u9898\u3002 \u8ba9\u903b\u8f91\u5c3d\u53ef\u80fd\u7b80\u5355\u76f4\u89c2\u3001\u7b26\u5408\u76f4\u89c9 \u2014\u2014 \u5728\u51fa\u73b0\u7d27\u6025\u95ee\u9898\u9700\u8981\u4fee\u590d\u65f6\uff0c\u6211\u5f88\u96be\u5feb\u901f\u7406\u89e3\u3001\u56de\u5fc6\u590d\u6742\u7684\u903b\u8f91\u3002 \u547d\u540d\u5177\u6709\u8db3\u591f\u6e05\u6670\u7684\u6307\u5411\u6027\uff0c\u4f7f\u7528 storageSize \u800c\u4e0d\u662f storage\uff0ctimeoutSeconds \u800c\u4e0d\u662f timeout \u2014\u2014 \u4fbf\u4e8e\u7406\u89e3\u4e14\u51cf\u5c11\u672a\u6765\u7684 breaking changes\u3002 \u7248\u672c\u9650\u5b9a\u5c3d\u53ef\u80fd\u4e25\u8c28\uff0c\u80fd\u6307\u5b9a\u5177\u4f53\u7248\u672c\u5c31\u4e0d\u4f7f\u7528 latest\uff0c\u4e0d\u901a\u8fc7\u590d\u7528 latest \u6765\u8282\u7ea6\u955c\u50cf\u4ed3\u5e93\u5927\u5c0f\u3002  \u4e0d\u8981\u5077\u61d2 \u4e0d\u8981\u5077\u61d2\u4f53\u73b0\u5728\u5f88\u591a\u7ec6\u8282\u4e0a\uff0c\u662f\u9700\u8981\u957f\u671f\u575a\u6301\u624d\u80fd\u770b\u5230\u6548\u679c\u7684\u8fc7\u7a0b\u3002\u5f80\u5f80\u505a\u7684\u65f6\u5019\u989d\u5916\u6d88\u8017\u4e86\u4e00\u4e9b\u7cbe\u529b\uff0c\u4f46\u5728\u672a\u6765\u6216\u662f\u65f6\u95f4\u7d27\u6025\u7684\u65f6\u5019\uff0c\u4e4b\u524d\u6295\u5165\u7684\u56de\u62a5\u7387\u4f1a\u5f88\u9ad8\u3002\u6bd4\u5982\uff1a\n \u5728 Commit Messages \u4e0a\u7cbe\u786e\u5730\u6982\u62ec\u6539\u52a8\u7684\u5185\u5bb9\uff0c\u9644\u4e0a\u76f8\u5173\u7684 Issue \u94fe\u63a5\u3001\u53c2\u8003\u8d44\u6599\u3002\u5f53\u51e0\u4e2a\u6708\u540e\u6211\u56de\u5fc6\u8d77\u76f8\u5173\u95ee\u9898\u65f6\uff0c\u80fd\u591f\u5feb\u901f\u5b9a\u4f4d\u76f8\u5173 Commit\uff0c\u4e14\u6709\u8bc1\u636e\u8bc1\u660e\u5f53\u65f6\u4e3a\u4ec0\u4e48\u8981\u8fd9\u4e48\u505a\u3002 \u53d1\u751f\u751f\u4ea7\u73af\u5883\u4e8b\u6545\u540e\uff0c\u590d\u76d8\u5e76\u603b\u7ed3\u8c03\u67e5\u62a5\u544a\u3002\u4e8b\u6545\u7684\u53d1\u751f\u5f80\u5f80\u4e0d\u662f\u5355\u4e00\u539f\u56e0\u9020\u6210\u7684\uff0c\u6211\u7684\u8bb0\u5fc6\u4e0d\u8db3\u4ee5\u652f\u6491\u6211\u8bb0\u4f4f\u66fe\u7ecf\u4e8b\u6545\u7684\u5168\u8fc7\u7a0b\uff0c\u6211\u9009\u62e9\u5c06\u5b83\u4eec\u8bb0\u4e0b\u6765\u3002 \u9664\u4e86\u5907\u4efd\uff0c\u8fd8\u8981\u505a\u597d\u6f14\u7ec3\uff0c\u7f16\u5199\u6210\u6587\u6863\u3002\u9700\u8981\u7d27\u6025\u6062\u590d\u73af\u5883\u65f6\uff0c\u6bcf\u5206\u6bcf\u79d2\u90fd\u975e\u5e38\u5b9d\u8d35\uff0c\u6709\u4e00\u4efd\u81ea\u5df1\u6f14\u7ec3\u603b\u7ed3\u800c\u6210\u7684\u3001\u80fd\u591f\u7acb\u523b\u53c2\u8003\u7684\u6587\u6863\u53ef\u4ee5\u8282\u7701\u5927\u91cf\u65f6\u95f4\u3002  \u7ed3\u8bed \u6211\u5f88\u559c\u6b22\u770b\u300a\u7a7a\u4e2d\u6d69\u52ab\u300b\u3002\u6211\u8ba4\u4e3a\uff0c\u67d0\u79cd\u610f\u4e49\u4e0a\u6765\u8bf4\uff0cDevOps \u5de5\u7a0b\u5e08\u7684\u89d2\u8272\u548c\u98de\u884c\u5458\u6709\u76f8\u4f3c\u4e4b\u5904 \u2014 \u9700\u8981\u901a\u8fc7\u300c\u7f16\u6392\u300d\u8ba9\u6574\u67b6\u98de\u673a\u987a\u5229\u8d77\u98de\uff0c\u9700\u8981\u63a5\u53d7\u5927\u91cf\u4fe1\u606f\u8f93\u5165\uff0c\u9700\u8981\u4e0e\u591a\u540d\u540c\u4e8b\u5bc6\u5207\u6c9f\u901a\u3001\u534f\u4f5c\uff0c\u9700\u8981\u5728\u6781\u77ed\u7684\u65f6\u95f4\u5185\u300c\u62ef\u6551\u300d\u6545\u969c\u7684\u98de\u673a\u3002\n\u6211\u70ed\u7231\u8fd9\u4efd\u5de5\u4f5c\uff0c\u76f8\u4fe1 2021 \u5e74\uff0c\u6211\u4f9d\u7136\u80fd\u591f\u505a\u4e00\u540d\u4f18\u79c0\u7684 DevOps \u5de5\u7a0b\u5e08\uff0c\u7ee7\u7eed\u5b88\u62a4\u98de\u673a\u5e73\u7a33\u822a\u884c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/my-work-skills-2021\/","summary":"<p>2020 \u5e74\u8f6c\u773c\u7ed3\u675f\u4e86\uff0c\u672c\u60f3\u5199\u5e74\u7ec8\u603b\u7ed3\u548c\u65b0\u5e74\u8ba1\u5212\uff0c\u5374\u53d1\u73b0 2020 \u5e74\u9664\u4e86\u6280\u672f\u8fdb\u6b65\uff0c\u8fd8\u603b\u7ed3\u4e86\u4e0d\u5c11\u6211\u81ea\u5df1\u7684\u300c\u5de5\u4f5c\u6280\u5de7\u300d\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u53eb\u505a\u300c\u5de5\u4f5c\u5b88\u5219\u300d\u3002\u6211\u9075\u5faa\u7740\u8fd9\u4e9b\u5b9e\u8df5\u4e2d\u603b\u7ed3\u51fa\u6765\u7684\u65b9\u6cd5\u5de5\u4f5c\uff0c\u4e3a\u6211\u81ea\u5df1\u4ee5\u53ca\u6211\u6240\u5728\u7684\u5c97\u4f4d\uff0c\u5e26\u6765\u4e86\u4e0d\u5c0f\u7684\u65f6\u95f4\u6548\u76ca\u548c\u7ecf\u6d4e\u6548\u76ca\u3002<\/p>\n<p>\u5f53\u7136\uff0c\u9002\u5408\u81ea\u5df1\u7684\u624d\u662f\u6700\u597d\u7684\uff0c\u6211\u4e0d\u559c\u6b22\u4e00\u5473\u6a21\u4eff\u5176\u5b83\u4eba\uff0c\u5e0c\u671b\u4f60\u4e5f\u5e26\u7740\u8fd9\u79cd\u60f3\u6cd5\u8bfb\u8fd9\u7bc7\u535a\u5ba2\u3002<\/p>","title":"\u6211\u7684\u5de5\u4f5c\u65b9\u6cd5"},{"content":"\u8fd9\u51e0\u5929\u60f3\u7ed9\u5bb6\u91cc\u4e0a\u300c\u53cc\u7f51\u300d\uff0c\u4f46\u5f31\u7535\u7bb1\u53ea\u6709\u4e00\u6839\u5149\u7ea4\uff0c\u6240\u4ee5\u65e0\u6cd5\u62c9\u53cc\u7ebf\u3002\u6b63\u597d\u624b\u4e0a\u6709\u4e00\u4e2a \u534e\u4e3a 5G \u968f\u8eab Wi-Fi Pro\uff0c\u5e72\u8106\u7528\u5b83\u6765\u505a Failover\uff08\u6545\u969c\u8f6c\u79fb\uff09\u5427\u3002\n\u76ee\u6807 \u76ee\u6807\u7f51\u7edc\u62d3\u6251\u5927\u6982\u662f\u8fd9\u6837\uff1a\n+-------------+ +-----------+ | Fiber Modem | | 5G Dongle | +----+--------+ +--------+--+ | | Ethernet USB Cable | | | | | | | +----ESXi Host----+ | | | | | +--&gt;+ OpenWrt VM +&lt;-+ | ... Other VMs | | | +-----------------+ \u8ba1\u5212  \u628a 5G Dongle \u6302\u8f7d\u5230 OpenWrt VM \u7684 USB Controller\uff0c\u6216\u8005\u628a\u4e3b\u677f\u4e0a\u7684 USB Controller \u76f4\u901a\u8fdb OpenWrt VM\u3002 \u5728 OpenWrt \u5b89\u88c5 usb-modeswitch \u7528\u4e8e\u628a CDROM Mode \u5207\u6362\u5230 Tethering Mode\u3002 \u5728 OpenWrt \u5b89\u88c5 USB Tethering \u76f8\u5173\u7684\u8f6f\u4ef6\u5305\uff0c\u5e76\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u63a5\u53e3\uff0c\u548c Tethering \u7684\u7269\u7406\u63a5\u53e3\u6865\u63a5\u3002 \u4f7f\u7528 mwan3 \u4e4b\u7c7b\u7684\u5de5\u5177\u5b9e\u73b0 Failover \u81ea\u52a8\u5207\u6362\u3002  ESXi \u76f4\u901a USB Controller \u5728\u5f00\u59cb\u4e4b\u524d\uff0c\u6211\u5148\u8bd5\u4e86\u4e0b\u628a 5G Dongle \u76f4\u63a5\u63d2 ESXi \u7269\u7406\u673a\uff0c\u9ed8\u8ba4\u5e94\u8be5\u4e3a CDROM \u6a21\u5f0f\uff0c\u679c\u4e0d\u5176\u7136\u5728 ESXi \u63a7\u5236\u53f0\u53d1\u73b0\u5b83\u88ab\u8bc6\u522b\u4e3a Storage\u3002\u4e3a\u4e86\u517c\u5bb9\u6027\uff0c\u518d\u52a0\u4e0a\u4e0d\u60f3\u6df1\u5165 ESXi\uff08\u6253\u7b97\u540e\u671f\u6362 PVE\uff09\uff0c\u5e72\u8106\u7b80\u5355\u70b9 \u2014 \u76f4\u901a\u4e3b\u677f\u4e0a\u7684 USB Controller\u3002\n  \u767b\u5f55 ESXi web console\uff0c\u5728\u5de6\u4fa7\u83dc\u5355\u4f9d\u6b21\u8fdb\u5165 Host -&gt; Manage -&gt; Hardware -&gt; PCI Devices\uff0c\u9009\u4e2d\u4f60\u7684 USB Controller\uff0c\u8bb0\u4f4f\u4e0b\u65b9\u7684 Device ID \u548c Vendor ID\u3002   SSH \u767b\u5f55 ESXi\uff0c\u4fee\u6539 \/etc\/vmware\/passthru.map \u6587\u4ef6\uff0c\u65b0\u589e\u4ee5\u4e0b\u51e0\u884c\uff1a\n# Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller 8086 9d2f d3d0 false \u5176\u4e2d\uff0c8086 \u662f Vendor ID\uff0c9d2f \u662f Device ID\uff0c\u968f\u540e\u4e24\u9879\u56fa\u5b9a\u3002\n  \u91cd\u542f ESXi Host\uff0c\u518d\u6b21\u767b\u5f55 web console \u5e76\u627e\u5230 USB Controller\uff0c\u70b9\u51fb\u4e0a\u65b9 Toggle passthrough \u6309\u94ae\u3002\u518d\u6b21\u91cd\u542f ESXi Host\uff0c\u786e\u8ba4\u53f3\u4fa7 Passthrough \u4e00\u680f\u4e3a Active \u5373\u53ef\u3002   \u5173\u673a OpenWrt VM\uff0c\u5e76\u65b0\u589e PCI Device\uff0c\u9009\u62e9\u4f60\u7684 USB Controller\u3002   \u4fee\u6539 VM \u7684\u5185\u5b58\u914d\u7f6e\uff0c\u5c06 Reservation \u4e0e RAM \u4fdd\u6301\u4e00\u81f4\uff08\u9009\u4e2d Reserve all guest memory (All locked)\uff09\u3002   \u628a 5G Dongle \u901a\u8fc7 USB \u63a5\u5165 ESXi Host\uff0c\u542f\u52a8 OpenWrt VM\u3002\n  \u5b89\u88c5 usb-modeswitch   SSH \u767b\u5f55 OpenWrt\uff0c\u6267\u884c\uff1a\nopkg update opkg install usbutils usb-modeswitch   \u91cd\u65b0\u63d2\u62d4 5G Dongle\uff0c\u6216\u8005\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u91cd\u542f usbmode \u670d\u52a1\uff1a\nservice usbmode restart   \u6267\u884c lsusb\uff0c\u5e94\u5f53\u80fd\u770b\u5230\u534e\u4e3a 5G \u968f\u8eab Wi-Fi \u7684\u5f71\u5b50\u4e86\uff1a\n... Bus 006 Device 002: ID 12d1:14db Huawei Technologies Co., Ltd. E353\/E3131 ... \u6ce8\u610f\u6b64\u884c\u7ed3\u5c3e\u6ca1\u6709 (Mass storage mode) \u4e4b\u7c7b\u7684\u5b57\u6837\uff0c\u8bf4\u660e usb-modeswitch \u6210\u529f\u5c06\u8bbe\u5907\u5207\u6362\u5230 Tethering \u6a21\u5f0f\u4e86\u3002\n  \u5b89\u88c5 USB Tethering \u9700\u8981\u7684\u8f6f\u4ef6\u5305 opkg install kmod-nls-base kmod-usb-core kmod-usb-net kmod-usb-net-rndis kmod-usb-net-cdc-ether kmod-usb2 kmod-usb3 \u521b\u5efa\u6865\u63a5\u7f51\u7edc\u63a5\u53e3   \u5982\u56fe\uff0c\u521b\u5efa\u65b0\u7684 Interface\uff0c\u6865\u63a5\u5230 eth3\uff08\u56e0\u4eba\u800c\u5f02\uff09\uff0c\u70b9\u51fb Create Interface\u3002   \u5207\u6362\u5230 Firewall Settings \u6807\u7b7e\u9875\uff0c\u5206\u914d Firewall-zone wan\u3002   \u5b89\u88c5 mwan3 \u5b9e\u73b0 Failover opkg install mwan3 luci-app-mwan3 luci-i18n-mwan3-zh-cn \u6700\u540e\uff0c\u901a\u8fc7 LuCI \u6216\u662f\u76f4\u63a5\u4fee\u6539\u914d\u7f6e\u6587\u4ef6 \/etc\/config\/mwan3 \u5747\u53ef\uff0c\u4f8b\u5982\u6211\u7684\u914d\u7f6e\u6587\u4ef6\u5982\u4e0b\uff1a\nconfig globals 'globals' option mmx_mask '0x3F00' option rtmon_interval '5' config interface 'wan' option enabled '1' option family 'ipv4' option count '1' option timeout '2' option interval '5' option down '3' option up '8' option initial_state 'online' option track_method 'ping' option size '56' option max_ttl '60' option check_quality '0' option failure_interval '5' option recovery_interval '5' option reliability '2' list track_ip '218.2.2.2' list track_ip '119.29.29.29' list track_ip '223.5.5.5' list track_ip '114.114.114.114' config interface 'wanb' option family 'ipv4' option count '1' option timeout '2' option interval '5' option down '3' option up '8' option initial_state 'online' option track_method 'ping' option size '56' option max_ttl '60' option check_quality '0' option failure_interval '5' option recovery_interval '5' option enabled '1' list track_ip '218.2.2.2' list track_ip '119.29.29.29' list track_ip '223.5.5.5' list track_ip '114.114.114.114' option reliability '2' config member 'wan_m1_w3' option interface 'wan' option metric '1' option weight '3' config member 'wan_m2_w3' option interface 'wan' option metric '2' option weight '3' config member 'wanb_m1_w2' option interface 'wanb' option metric '1' option weight '2' config member 'wanb_m2_w2' option interface 'wanb' option metric '2' option weight '2' config policy 'wan_only' list use_member 'wan_m1_w3' list use_member 'wan6_m1_w3' config policy 'wanb_only' list use_member 'wanb_m1_w2' list use_member 'wanb6_m1_w2' config policy 'balanced' list use_member 'wan_m1_w3' list use_member 'wanb_m1_w2' list use_member 'wan6_m1_w3' list use_member 'wanb6_m1_w2' config policy 'wan_wanb' list use_member 'wan_m1_w3' list use_member 'wanb_m2_w2' list use_member 'wan6_m1_w3' list use_member 'wanb6_m2_w2' config policy 'wanb_wan' list use_member 'wan_m2_w3' list use_member 'wanb_m1_w2' list use_member 'wan6_m2_w3' list use_member 'wanb6_m1_w2' config rule 'default_rule_v4' option dest_ip '0.0.0.0\/0' option family 'ipv4' option proto 'all' option sticky '0' option use_policy 'failover' config rule 'default_rule_v6' option dest_ip '::\/0' option family 'ipv6' option proto 'all' option sticky '0' option use_policy 'default' config policy 'failover' list use_member 'wan_m1_w3' list use_member 'wanb_m2_w2' option last_resort 'unreachable' \u53c2\u8003\u6587\u732e  https:\/\/lx-soft.net\/archives\/242 https:\/\/openwrt.org\/docs\/guide-user\/network\/wan\/wwan\/3gdongle https:\/\/openwrt.org\/docs\/guide-user\/storage\/usb-installing https:\/\/openwrt.org\/docs\/guide-user\/network\/wan\/smartphone.usb.tethering ","permalink":"https:\/\/wi1dcard.dev\/posts\/huawei-5g-dongle-usb-tethering-with-openwrt-in-esxi\/","summary":"<p>\u8fd9\u51e0\u5929\u60f3\u7ed9\u5bb6\u91cc\u4e0a\u300c\u53cc\u7f51\u300d\uff0c\u4f46\u5f31\u7535\u7bb1\u53ea\u6709\u4e00\u6839\u5149\u7ea4\uff0c\u6240\u4ee5\u65e0\u6cd5\u62c9\u53cc\u7ebf\u3002\u6b63\u597d\u624b\u4e0a\u6709\u4e00\u4e2a <a href=\"https:\/\/consumer.huawei.com\/en\/routers\/5g-mobile-wifi-pro\/\" target=\"_blank\">\u534e\u4e3a 5G \u968f\u8eab Wi-Fi Pro<\/a>\uff0c\u5e72\u8106\u7528\u5b83\u6765\u505a Failover\uff08\u6545\u969c\u8f6c\u79fb\uff09\u5427\u3002<\/p>","title":"ESXi OpenWrt \u4f7f\u7528\u534e\u4e3a\u968f\u8eab Wi-Fi \u5b9e\u73b0 WAN \u6545\u969c\u8f6c\u79fb"},{"content":"\u591a\u4e8f\u4e86 prometheus-webhook-dingtalk \u9879\u76ee\uff0cAlertmanager \u96c6\u6210\u9489\u9489\u6d88\u606f\u901a\u77e5\u5f97\u4ee5\u5b9e\u73b0\u3002\u5728\u5b9e\u9645\u4f7f\u7528\u8fc7\u7a0b\u4e2d\uff0c\u6211\u53d1\u73b0\u4e86\u4e00\u4e9b\u53ef\u4ee5\u6539\u8fdb\u7684\u914d\u7f6e\uff0c\u4f8b\u5982\u901a\u77e5\u6d88\u606f\u6a21\u677f\u53ef\u4ee5\u66f4\u52a0\u6e05\u6670\u7b80\u6d01\u3001\u53ef\u4ee5\u6839\u636e\u4e0d\u540c\u7684\u62a5\u8b66\u4f18\u5148\u7ea7\u51b3\u5b9a\u662f\u5426 Mention \u67d0\u4eba\u7b49\u3002\n\u6539\u8fdb\u901a\u77e5\u6a21\u677f \u6539\u8fdb\u524d\uff1a\n\u6539\u8fdb\u540e\uff1a\n\u5177\u4f53\u6a21\u677f\uff08\/config\/example.tmpl\uff09\uff1a\n{{\/* Alert List Begin *\/}} {{ define &#34;example.__text_alert_list&#34; }}{{ range . }} **{{ .Annotations.message }}** [Prometheus]({{ .GeneratorURL }}) | [Alertmanager](https:\/\/alertmanager.example.com\/#\/alerts) | [Grafana](https:\/\/grafana.example.com\/dashboards)  {{ range .Labels.SortedPairs }}&gt; - {{ .Name }}: {{ .Value | markdown | html }} {{ end }} {{ end }}{{ end }} {{\/* Alert List End *\/}} {{\/* Message Title Begin *\/}} {{ define &#34;example.title&#34; }}{{ template &#34;__subject&#34; . }}{{ end }} {{\/* Message Title End *\/}} {{\/* Message Content Begin *\/}} {{ define &#34;example.content&#34; }} ### \\[{{ index .GroupLabels &#34;priority&#34; }}\\] [{{ index .GroupLabels &#34;alertname&#34; }}](https:\/\/example.app.opsgenie.com\/alert\/list)  {{ if gt (len .Alerts.Firing) 0 -}} {{ template &#34;example.__text_alert_list&#34; .Alerts.Firing }} {{- end }} {{ if gt (len .Alerts.Resolved) 0 -}} {{ template &#34;example.__text_alert_list&#34; .Alerts.Resolved }} {{- end }} {{- end }} {{\/* Message Content End *\/}} prometheus-webhook-dingtalk \u914d\u7f6e\uff1a\ntemplates: - \/config\/example.tmpl # \u6a21\u677f\u8def\u5f84 targets: general: url: https:\/\/oapi.dingtalk.com\/robot\/send?access_token=... secret: ... message: title: &#39;{{ template &#34;example.title&#34; . }}&#39; # \u6e32\u67d3\u81ea\u5b9a\u4e49\u6a21\u677f text: &#39;{{ template &#34;example.content&#34; . }}&#39; # \u6e32\u67d3\u81ea\u5b9a\u4e49\u6a21\u677f Mention \u6d77\u5916\u53f7\u7801 \u8bf7\u770b PR #119 \u6216\u4e0b\u9762\u7684\u4f8b\u5b50\u3002\n\u9009\u62e9\u6027 Mention \u67d0\u4eba \u9996\u5148\u914d\u7f6e\u4e24\u4e2a targets\uff0c\u524d\u8005\u76f4\u63a5\u6e32\u67d3\u6a21\u677f\uff0c\u540e\u8005\u6a21\u677f\u4e2d\u518d\u6dfb\u52a0\u4e00\u884c ###### @\u624b\u673a\u53f7\uff08\u663e\u793a\u6548\u679c\u53ef\u4ee5\u53c2\u8003\u6587\u7ae0\u5f00\u5934\u7684\u56fe\u7247\uff09\uff1a\ntargets: general: &amp;target_base url: https:\/\/oapi.dingtalk.com\/robot\/send?access_token=... secret: ... message: title: &#39;{{ template &#34;example.title&#34; . }}&#39; text: &#39;{{ template &#34;example.content&#34; . }}&#39; critical: &lt;&lt;: *target_base mention: # \u6b64\u5904\u5fc5\u987b\u58f0\u660e Mention \u7684\u53f7\u7801... mobiles: [&#34;+1-1234567890&#34;, &#34;18800001111&#34;] message: text: |###### @+1-1234567890 @18800001111 {{ template &#34;example.content&#34; . }} \u968f\u540e\u5728 Alertmanager \u914d\u7f6e\u4e24\u4e2a\u5206\u522b\u5bf9\u5e94\u7684 receivers\uff0c\u4ee5\u53ca\u591a\u6761 routes \u5373\u53ef\uff1a\nroute: group_by: [&#34;priority&#34;, &#34;alertname&#34;] receiver: general routes: - match_re: priority: P1 receiver: critical receivers: - name: general webhook_configs: - &amp;dingtalk_config send_resolved: false url: http:\/\/alertmanager-webhook-dingtalk\/dingtalk\/general\/send - name: critical webhook_configs: - &lt;&lt;: *dingtalk_config url: http:\/\/alertmanager-webhook-dingtalk\/dingtalk\/critical\/send ","permalink":"https:\/\/wi1dcard.dev\/posts\/alertmanager-dingtalk-integration-tips\/","summary":"<p>\u591a\u4e8f\u4e86 <a href=\"https:\/\/github.com\/timonwong\/prometheus-webhook-dingtalk\" target=\"_blank\">prometheus-webhook-dingtalk<\/a> \u9879\u76ee\uff0cAlertmanager \u96c6\u6210\u9489\u9489\u6d88\u606f\u901a\u77e5\u5f97\u4ee5\u5b9e\u73b0\u3002\u5728\u5b9e\u9645\u4f7f\u7528\u8fc7\u7a0b\u4e2d\uff0c\u6211\u53d1\u73b0\u4e86\u4e00\u4e9b\u53ef\u4ee5\u6539\u8fdb\u7684\u914d\u7f6e\uff0c\u4f8b\u5982\u901a\u77e5\u6d88\u606f\u6a21\u677f\u53ef\u4ee5\u66f4\u52a0\u6e05\u6670\u7b80\u6d01\u3001\u53ef\u4ee5\u6839\u636e\u4e0d\u540c\u7684\u62a5\u8b66\u4f18\u5148\u7ea7\u51b3\u5b9a\u662f\u5426 Mention \u67d0\u4eba\u7b49\u3002<\/p>","title":"\u6539\u8fdb Alertmanager \u7684\u9489\u9489\u901a\u77e5"},{"content":"In kubernetes-mixin (a dependency of kube-prometheus-stack and prometheus-operator charts) rules, the severity label of alrets can be critical, warning, or info etc. However, OpsGenie&rsquo;s priority field only accepts values like P1, P2 &hellip; P5.\nAs a user of both of them, I would have to convert the &ldquo;severity&rdquo; to OpsGenie&rsquo;s &ldquo;priority&rdquo;. For example, if a critical alert was fired, a matched P1 alert to be created in OpsGenie is expected, and warning -&gt; P2, info -&gt; P3, as well.\nWe can use go-template in receivers.*.opsgenie_configs.*.priority of Alertmanager&rsquo;s config to generate the priority. However it will finnally end with something like:\npriority: &gt;-{{ with .GroupLabels.priority }} {{ if eq . &#34;critical&#34; }} P1 {{ else if eq . &#34;warning&#34; }} P2 {{ else if ... }} ... {{ end }} That&rsquo;s a bit hard to maintain or debug, and I personnaly don&rsquo;t really like to write tons of go-templates in a short config file, it should be much clearer. Therefore, I prefer the second way - use the relabel_config in Prometheus, instead of doing this in Alertmanager.\nIf you&rsquo;re using kube-prometheus-stack (formerly known as prometheus-operator chart), just add these configs in prometheus.prometheusSpec.additionalAlertRelabelConfigs:\nadditionalAlertRelabelConfigs: - source_labels: [severity] target_label: priority regex: &#34;none&#34; # Seem only the WatchDog alert has &#34;none&#34; severity replacement: &#34;P5&#34; - source_labels: [severity] target_label: priority regex: &#34;info&#34; replacement: &#34;P3&#34; - source_labels: [severity] target_label: priority regex: &#34;warning&#34; replacement: &#34;P2&#34; - source_labels: [severity] target_label: priority regex: &#34;critical&#34; replacement: &#34;P1&#34; And use the grouped label in Alertmanager&rsquo;s priority field:\npriority: {{ .GroupLabels.priority }} These relabel configs will apply to alerts only, add the priority label according to the value of severity. This also makes it easier to debug - if the alert priority in your OpsGenie dashboard is not correct, just go check out Alertmanager&rsquo;s dashboard, it shows directly the labels of the alerts included priority sent from Prometheus! But if we made a lot of logic in Alertmanager&rsquo;s go-template, I can&rsquo;t seem to find a simple way to get the value of the rendered results in Alertmanager&rsquo;s templating context.\nFor more information about alert_relabel_configs, please check out Prometheus official docs.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/prometheus-severity-label-to-opsgenie-priority\/","summary":"<p>In <a href=\"https:\/\/github.com\/kubernetes-monitoring\/kubernetes-mixin\" target=\"_blank\">kubernetes-mixin<\/a> (a dependency of <a href=\"https:\/\/github.com\/prometheus-community\/helm-charts\/tree\/main\/charts\/kube-prometheus-stack\" target=\"_blank\">kube-prometheus-stack<\/a> and <a href=\"https:\/\/github.com\/helm\/charts\/tree\/d0f9bcc80f0282519bee34d81175895c8a776b1f\/stable\/prometheus-operator\" target=\"_blank\">prometheus-operator<\/a> charts) rules, the severity label of alrets can be <code>critical<\/code>, <code>warning<\/code>, or <code>info<\/code> etc. However, OpsGenie&rsquo;s priority field only accepts values like <code>P1<\/code>, <code>P2<\/code> &hellip; <code>P5<\/code>.<\/p>\n<p>As a user of both of them, I would have to convert the &ldquo;severity&rdquo; to OpsGenie&rsquo;s &ldquo;priority&rdquo;. For example, if a <code>critical<\/code> alert was fired, a matched <code>P1<\/code> alert to be created in OpsGenie is expected, and <code>warning<\/code> -&gt; <code>P2<\/code>, <code>info<\/code> -&gt; <code>P3<\/code>, as well.<\/p>","title":"Convert Kubernetes-Mixin Severities to OpsGenie Priorities in Prometheus"},{"content":"\u4e00\u822c\u6765\u8bf4\uff0c\u76d1\u63a7 Substrate \u6846\u67b6\u5f00\u53d1\u7684\u533a\u5757\u94fe\u8282\u70b9\uff0c\u53ef\u4ee5\u4f7f\u7528\u5b98\u65b9\u63a8\u8350\u7684 Prometheus + Grafana \u6280\u672f\u6808\u3002\u5728\u8282\u70b9\u6570\u91cf\u6bd4\u8f83\u591a\u7684\u60c5\u51b5\u4e0b\uff0c\u8fd9\u5957\u65b9\u6848\u7684\u4f18\u52bf\u6bd4\u8f83\u5bb9\u6613\u4f53\u73b0\u51fa\u6765\uff0c\u6211\u7ed9\u516c\u53f8\u7684\u5b98\u65b9\u8282\u70b9\u4e5f\u662f\u8fd9\u4e48\u914d\u7684\u3002\u4e0d\u8fc7\u8fd1\u671f Darwinia \u4e3b\u7f51\u4e0a\u7ebf\uff0c\u6709\u4e0d\u5c11\u540c\u4e8b\u60f3\u8981\u8dd1\u81ea\u5df1\u7684\u9a8c\u8bc1\u4eba\uff08validator\uff09\u8282\u70b9\u3002\u5bf9\u4e8e\u4ed6\u4eec\u6765\u8bf4\uff1a\n \u642d\u5efa\u4e00\u5957 Prometheus \u8fd8\u8981\u81ea\u5df1\u8c03\u9762\u677f\u548c\u89c4\u5219\uff0c\u6210\u672c\u5b9e\u5728\u592a\u9ad8\uff1b \u53ea\u7528 PM2\u3001Supervisord\u3001Systemd \u4e4b\u7c7b\u7684\u5b88\u62a4\u8fdb\u7a0b\u901a\u5e38\u53ea\u80fd\u4fdd\u8bc1\u8fdb\u7a0b\u6ca1\u6302\uff0c\u4f46\u8282\u70b9\u662f\u5426\u6b63\u5e38\u51fa\u5757\u662f\u672a\u77e5\u7684\uff08\u4f8b\u5982\u65ad\u7f51\u30010 Peer \u7684\u60c5\u51b5\uff0c\u8282\u70b9\u8fdb\u7a0b\u8fd8\u5728\uff0c\u5176\u5b9e\u5df2\u7ecf\u6389\u7ebf\u4e86\uff09\u3002  \u4e3a\u4e86\u89e3\u51b3\u4ee5\u4e0a\u8fd9\u4e24\u4e2a\u95ee\u9898\uff0c\u6211\u641e\u4e86\u4e00\u5957\u975e\u5e38\u7b80\u6613\u7684\u3001\u57fa\u4e8e\u65e5\u5fd7\u7684\u76d1\u63a7\u9884\u8b66\u65b9\u6cd5\u3002\n \ud83d\ude80 KUBE-VALI \u662f\u57fa\u4e8e Kubernetes \u96c6\u7fa4\u5927\u89c4\u6a21\u90e8\u7f72\u7684\u8282\u70b9\uff0c\u7a33\u5b9a\u53ef\u9760\uff0c\u6c42\u5927\u4f6c\u6295\u7968\u3002\n \u57fa\u672c\u601d\u8def \u57fa\u4e8e Darwinia \u9a8c\u8bc1\u4eba\u4ea7\u5757\uff0c\u4f1a\u6709\u7c7b\u4f3c \ud83c\udf81 Prepared block for proposing at ... \u7684\u65e5\u5fd7\u8f93\u51fa\uff0c\u53ea\u8981\u6709\u4e2a\u811a\u672c\u4e0d\u65ad\u68c0\u67e5\u8282\u70b9\u65e5\u5fd7\uff0c\u5982\u679c\u4e00\u6bb5\u65f6\u95f4\u5185\u6ca1\u6709\u7c7b\u4f3c\u7684\u8f93\u51fa\uff0c\u8bf4\u660e\u8282\u70b9\u53ef\u80fd\u5df2\u7ecf\u51fa\u4e86\u95ee\u9898\uff0c\u53d1\u9001\u901a\u77e5\u6216\u91cd\u542f\u8282\u70b9\u5747\u53ef\u3002\n\u6700\u7ec8\u6548\u679c \u5177\u4f53\u6b65\u9aa4 1) \u5b9e\u73b0\u68c0\u67e5\u65e5\u5fd7 \u9996\u5148\u767b\u5f55\u4f60\u7684\u9a8c\u8bc1\u4eba\u8282\u70b9\uff0c\u521b\u5efa\u4e00\u4e2a Watchlog \u811a\u672c\uff0c\u4f8b\u5982 \/usr\/bin\/darwinia-watchlog.sh\uff1a\n#!\/usr\/bin\/env bash  RETRIVE_LOG_COMMAND=&#34;journalctl -u darwinia-node.service -o cat --since -30m&#34; # RETRIVE_LOG_COMMAND=&#34;docker logs darwinia-node --since 30m&#34; echo &#34;[INFO] Checking Darwinia logs...&#34; DARWINIA_LOGS=&#34;$($RETRIVE_LOG_COMMAND | grep &#39;Prepared block&#39;)&#34; if [ $? -eq 0 ]; then echo &#34;[INFO] New blocks detected.&#34; else echo &#34;[WARN] No blocks deteched!&#34; fi  RETRIVE_LOG_COMMAND \u662f\u7528\u6765\u83b7\u53d6\u8fd1\u671f\u8282\u70b9\u65e5\u5fd7\u7684\u547d\u4ee4\u3002\u6211\u5217\u51fa\u4e86\u4e24\u4e2a\u4f8b\u5b50\uff0c\u524d\u8005\u9002\u7528\u4e8e Systemd \u542f\u52a8\u7684\u8282\u70b9\uff0c\u540e\u8005\u9002\u7528\u4e8e Docker \u542f\u52a8\u7684\u8282\u70b9\uff0c\u4f60\u53ef\u4ee5\u4efb\u610f\u4fee\u6539\u5b83\u3002 'Prepared block' \u662f\u5728\u65e5\u5fd7\u91cc\u67e5\u627e\u7684\u5173\u952e\u8bcd\uff0c\u4f60\u4e5f\u53ef\u4ee5\u4fee\u6539\u4e3a 'Imported' \u4e4b\u7c7b\u7684\u503c\u3002  \u968f\u540e\u8fd0\u884c\u8be5\u811a\u672c\uff0c\u4f1a\u53d1\u73b0\u6709 [INFO] New blocks detected. \u6216\u662f [WARN] No blocks deteched! \u7684\u8f93\u51fa\uff0c\u8bf4\u660e\u5b83\u5df2\u7ecf\u80fd\u591f\u6b63\u5e38\u68c0\u6d4b\u8282\u70b9\u65e5\u5fd7\u4e86\u3002\n2) \u6301\u7eed\u68c0\u67e5\u8282\u70b9\u65e5\u5fd7 \u4e3a\u4e86\u80fd\u591f \u6301\u7eed \u68c0\u67e5\u8282\u70b9\u65e5\u5fd7\uff0c\u6211\u4eec\u4f7f\u7528 Cron job \u6bcf\u5206\u949f \u8c03\u7528\u4e00\u6b21\u8be5\u811a\u672c\u5c31\u53ef\u4ee5\u4e86\u3002\u6267\u884c\u4ee5\u4e0b\u811a\u672c\u65b0\u589e\u4e00\u4e2a\u6bcf\u5206\u949f\u6267\u884c\u7684 Cron job\uff1a\n(crontab -l ; echo &#34;* * * * * \/usr\/bin\/darwinia-watchlog.sh | logger -t darwinia-watchlog&#34;) 2&gt;&amp;1 | grep -v &#34;no crontab&#34; | sort | uniq | crontab - 3) \u9884\u8b66\u901a\u77e5\u548c\u91cd\u542f \u81ea\u5df1\u5199\u901a\u77e5\u592a\u9ebb\u70e6\uff0c\u4e0d\u5982\u8bd5\u8bd5 https:\/\/healthchecks.io\/ \u5427\u3002Healthchecks.io \u662f\u4e00\u6b3e \u5f00\u6e90\u7684 \u5b9a\u65f6\u4efb\u52a1\u76d1\u63a7\u3001\u901a\u77e5\u7cfb\u7edf\u3002\u5b83\u5047\u8bbe\u4f60\u7684\u811a\u672c\u5728\u300c\u67d0\u4e00\u65f6\u523b\u300d\u8fd0\u884c\uff0c\u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u4f60\u7684\u811a\u672c\u8fd0\u884c\u6210\u529f\u5e76\u7ed9\u5b83\u53d1\u9001\u4e00\u4e2a\u6210\u529f\u6d88\u606f\uff1b\u5982\u679c\u4f60\u7684\u811a\u672c\u6ca1\u6709\u8fd0\u884c\uff0c\u6216\u662f\u6267\u884c\u51fa\u9519\uff0c\u5b83\u80fd\u591f\u6309\u7167\u6307\u5b9a\u7684\u901a\u77e5\u6e20\u9053\uff0c\u7ed9\u4f60\u53d1\u9001\u4e00\u6761\u9884\u8b66\u901a\u77e5\u3002\n\u6ce8\u518c\u540e\u9996\u5148\u5728 Integrations \u91cc\u6dfb\u52a0\u901a\u77e5\u6e20\u9053\uff0c\u4f8b\u5982\u6211\u6dfb\u52a0\u4e86\u6211\u7684 Telegram\uff1a\n\u968f\u540e\u5728 Checks \u9875\u9762\u70b9\u51fb Add Check \u65b0\u589e\u4e00\u4e2a Check\uff0c\u4f1a\u8df3\u5230\u65b0\u521b\u5efa\u7684 Check \u7684\u4fe1\u606f\u9875\u9762\uff1a\nSchedule \u662f\u80af\u5b9a\u8981\u6539\u7684\uff0c\u9700\u8981\u8ddf\u6211\u4eec\u811a\u672c\u7684\u5b9e\u9645\u8fd0\u884c\u8ba1\u5212\u5339\u914d\uff0c\u70b9\u51fb Change Schedule...\uff0c\u628a Period \u548c Grace Time \u5168\u90e8\u8c03\u6210 1 minute\uff1a\n\u6700\u540e\u70b9\u51fb Usage Examples...\uff0c\u627e\u5230 Bash \u7684\u4f8b\u5b50\uff0c\u590d\u5236\u8fd9\u884c\u547d\u4ee4\uff1a\n\u56de\u5230\u6211\u4eec\u7684\u8282\u70b9\u673a\u5668\u4e0a\uff0c\u4fee\u6539 \/usr\/bin\/darwinia-watchlog.sh \u811a\u672c\uff0c\u5728 echo &quot;[INFO] New blocks detected.&quot; \u4e4b\u540e\u6dfb\u52a0\u8fd9\u884c\u547d\u4ee4\u5c31\u53ef\u4ee5\u4e86\uff1a\n# ... if [ $? -eq 0 ]; then echo &#34;[INFO] New blocks detected.&#34; curl -m 10 --retry 5 https:\/\/hc-ping.com\/9a9ea2f6-1b6e-43c3-ba5a-000130ad0fd3 # \u5728\u8fd9\u91cc # ... \u8fd9\u6837\u6211\u4eec\u7684\u811a\u672c\u5728\u6bcf\u5206\u949f\u5b9a\u65f6\u6267\u884c\u65f6\uff0c\u5982\u679c\u6709\u68c0\u67e5\u5230\u65b0\u5757\u4ea7\u751f\uff0c\u5c31\u4f1a\u8f93\u51fa [INFO] New blocks detected.\uff0c\u5e76\u8c03\u7528 healthchecks.io\u3002\u5982\u679c\u6ca1\u6709\u68c0\u67e5\u5230\uff0c\u5c31\u4e0d\u4f1a\u8c03\u7528 healthchecks.io\uff0c\u8fdb\u800c healthchecks.io \u4f1a\u9ed8\u8ba4\u6267\u884c\u5931\u8d25\uff0c\u4ece\u800c\u53d1\u8d77\u901a\u77e5\u3002\n\u6700\u7ec8\u6539\u8fdb\u540e\u7684\u5b8c\u6574\u811a\u672c \u4f60\u53ef\u4ee5\u76f4\u63a5\u590d\u5236\u4ee5\u4e0b\u811a\u672c\uff0c\u6211\u8fd8\u505a\u4e86\u4e00\u4e9b\u5176\u5b83\u7684\u5c0f\u4f18\u5316\uff0c\u4fee\u6539 !!! HEALTH CHECK ID !!! \u5373\u53ef\u4f7f\u7528\u3002\n#!\/usr\/bin\/env bash  RETRIVE_LOG_COMMAND=&#34;journalctl -u darwinia-node.service -o cat --since -30m&#34; # RETRIVE_LOG_COMMAND=&#34;docker logs darwinia-node --since 30m&#34; HEALTHCHECK_IO_URL=&#34;https:\/\/hc-ping.com\/!!! HEALTH CHECK ID !!!&#34; # \u522b\u5fd8\u8bb0\u586b\u5165 Healthchecks.io \u7684 URL echo &#34;[INFO] Checking Darwinia logs...&#34; DARWINIA_LOGS=&#34;$($RETRIVE_LOG_COMMAND | grep &#39;Prepared block&#39;)&#34; if [ $? -eq 0 ]; then echo &#34;[INFO] New blocks detected.&#34; echo -n &#34;[INFO] Notifying healthchecks.io... &#34; curl -fsS --max-time 10 --retry 3 --data-raw &#34;$DARWINIA_LOGS&#34; &#34;$HEALTHCHECK_IO_URL&#34; else echo &#34;[WARN] No blocks deteched!&#34; echo -n &#34;[INFO] Notifying healthchecks.io... &#34; curl -fsS --max-time 10 --retry 3 &#34;$HEALTHCHECK_IO_URL\/fail&#34; fi \u4f60\u53ef\u4ee5\u6267\u884c journalctl SYSLOG_IDENTIFIER=darwinia-watchlog -f \u89c2\u5bdf\u811a\u672c\u8fd0\u884c\u65e5\u5fd7\uff1a\nSep 29 10:49:01 darwinia-watchlog[19493]: [INFO] Checking Darwinia logs... Sep 29 10:49:01 darwinia-watchlog[19493]: [INFO] New blocks detected. Sep 29 10:49:01 darwinia-watchlog[19493]: [INFO] Notifying healthchecks.io... OK Sep 29 10:50:01 darwinia-watchlog[19503]: [INFO] Checking Darwinia logs... Sep 29 10:50:01 darwinia-watchlog[19503]: [INFO] New blocks detected. Sep 29 10:50:02 darwinia-watchlog[19503]: [INFO] Notifying healthchecks.io... OK ... \u5199\u5728\u6700\u540e  \u5176\u5b9e\u8fd9\u4e2a\u65b9\u6848\u662f\u53d7\u5230 GCP Log-based metrics \u542f\u53d1\u800c\u5b9e\u73b0\u7684\uff0c\u6700\u65e9\u6211\u7684\u601d\u8def\u662f\u7528 ELK \u5206\u6790\u65e5\u5fd7\uff0c\u4f46\u67d0\u5929\u7a81\u7136\u7075\u5149\u4e00\u73b0 \u2014 \u6839\u672c\u4e0d\u7528\u8fd9\u4e48\u9ebb\u70e6\uff0c\u76f4\u63a5\u5199\u4e2a\u811a\u672c + CRON \u5b9a\u65f6\u6267\u884c + \u968f\u4fbf\u627e\u4e2a\u5916\u90e8\u76d1\u63a7\u5c31\u597d\u4e86\u3002 \u5176\u5b9e\u4e5f\u53ef\u4ee5\u4e0d\u7528 CRON\uff0c\u6539\u7528\u811a\u672c\u6b7b\u5faa\u73af\u4e5f\u53ef\u4ee5\u3002\u4e0d\u8fc7\u8fd9\u6837\u5c31\u589e\u52a0\u4e86\u811a\u672c\u672c\u8eab\u7684\u590d\u6742\u5ea6\uff0c\u53e6\u5916\u8fd8\u5f97\u5904\u7406\u5e38\u9a7b\u8fdb\u7a0b\u7b49\u95ee\u9898\u3002 \u53e6\u5916\u4e5f\u53ef\u4ee5\u4e0d\u7528 healthcheck.io\uff0c\u76f4\u63a5\u5728\u811a\u672c\u5185\u53d1\u901a\u77e5\u3002\u4f46\u540c\u6837\u5f97\u8003\u8651\uff1a\u4e07\u4e00\u811a\u672c\u4e5f\u5d29\u4e86\u600e\u4e48\u529e\uff1f\u5982\u679c\u9a8c\u8bc1\u4eba\u8282\u70b9\u5f7b\u5e95\u65ad\u7f51\uff0c\u6839\u672c\u53d1\u4e0d\u51fa\u6765\u901a\u77e5\u600e\u4e48\u529e\uff1f\u5355\u53f0\u673a\u5668\u65e0\u6cd5\u89e3\u51b3\uff0c\u518d\u5f00\u4e00\u53f0\u673a\u5668\u7528\u4f5c\u76d1\u63a7\u8fdd\u80cc\u4e86\u8fd9\u4e2a\u65b9\u6848\u7684\u521d\u5fc3\uff0c\u800c\u5229\u7528\u5916\u90e8\u7684\u3001\u88ab\u52a8\u7684\uff08\u5373\u4f7f\u673a\u5668\u6302\u4e86\u53d1\u4e0d\u51fa\u6765\u901a\u77e5\u4e5f\u80fd\u88ab\u76d1\u63a7\u6355\u6349\u5230\uff09\u76d1\u63a7\u670d\u52a1\u662f\u6211\u76ee\u524d\u80fd\u60f3\u5230\u6210\u672c\u6700\u4f4e\u5ec9\u7684\u89e3\u51b3\u65b9\u6848\u4e86\u3002 ","permalink":"https:\/\/wi1dcard.dev\/posts\/darwinia-validators-log-based-monitoring\/","summary":"<p>\u4e00\u822c\u6765\u8bf4\uff0c\u76d1\u63a7 Substrate \u6846\u67b6\u5f00\u53d1\u7684\u533a\u5757\u94fe\u8282\u70b9\uff0c\u53ef\u4ee5\u4f7f\u7528\u5b98\u65b9\u63a8\u8350\u7684 Prometheus + Grafana \u6280\u672f\u6808\u3002\u5728\u8282\u70b9\u6570\u91cf\u6bd4\u8f83\u591a\u7684\u60c5\u51b5\u4e0b\uff0c\u8fd9\u5957\u65b9\u6848\u7684\u4f18\u52bf\u6bd4\u8f83\u5bb9\u6613\u4f53\u73b0\u51fa\u6765\uff0c\u6211\u7ed9\u516c\u53f8\u7684\u5b98\u65b9\u8282\u70b9\u4e5f\u662f\u8fd9\u4e48\u914d\u7684\u3002\u4e0d\u8fc7\u8fd1\u671f Darwinia \u4e3b\u7f51\u4e0a\u7ebf\uff0c\u6709\u4e0d\u5c11\u540c\u4e8b\u60f3\u8981\u8dd1\u81ea\u5df1\u7684\u9a8c\u8bc1\u4eba\uff08<code>validator<\/code>\uff09\u8282\u70b9\u3002\u5bf9\u4e8e\u4ed6\u4eec\u6765\u8bf4\uff1a<\/p>\n<ul>\n<li>\u642d\u5efa\u4e00\u5957 Prometheus \u8fd8\u8981\u81ea\u5df1\u8c03\u9762\u677f\u548c\u89c4\u5219\uff0c\u6210\u672c\u5b9e\u5728\u592a\u9ad8\uff1b<\/li>\n<li>\u53ea\u7528 PM2\u3001Supervisord\u3001Systemd \u4e4b\u7c7b\u7684\u5b88\u62a4\u8fdb\u7a0b\u901a\u5e38\u53ea\u80fd\u4fdd\u8bc1\u8fdb\u7a0b\u6ca1\u6302\uff0c\u4f46\u8282\u70b9\u662f\u5426\u6b63\u5e38\u51fa\u5757\u662f\u672a\u77e5\u7684\uff08\u4f8b\u5982\u65ad\u7f51\u30010 Peer \u7684\u60c5\u51b5\uff0c\u8282\u70b9\u8fdb\u7a0b\u8fd8\u5728\uff0c\u5176\u5b9e\u5df2\u7ecf\u6389\u7ebf\u4e86\uff09\u3002<\/li>\n<\/ul>\n<p>\u4e3a\u4e86\u89e3\u51b3\u4ee5\u4e0a\u8fd9\u4e24\u4e2a\u95ee\u9898\uff0c\u6211\u641e\u4e86\u4e00\u5957\u975e\u5e38\u7b80\u6613\u7684\u3001\u57fa\u4e8e\u65e5\u5fd7\u7684\u76d1\u63a7\u9884\u8b66\u65b9\u6cd5\u3002<\/p>","title":"\u8d85\u7b80\u5355\uff01\u57fa\u4e8e\u65e5\u5fd7\u7684 Darwinia \u9a8c\u8bc1\u4eba\u8282\u70b9\u76d1\u63a7\u9884\u8b66"},{"content":"\u963f\u91cc\u4e91\u6536\u8d2d\u4e07\u7f51\u4e4b\u540e\uff0c\u51e0\u4e4e\u4e0d\u8d5a\u94b1\u7684\u90ae\u4ef6\u670d\u52a1\u8fd8\u771f\u662f\u4e0d\u7ef4\u62a4\u4e0d\u8fed\u4ee3\u4e86 \u2014 \u4e0d\u652f\u6301 DKIM\uff0c\u6ca1\u6cd5\u914d DMARC\uff0c\u5c31\u8fde SMTP \u4e5f\u4e0d\u652f\u6301 STARTTLS 587 \u7aef\u53e3\u3002\n# ... receivers: - name: email email_configs: - send_resolved: true to: name@yourcompany.com from: name@yourcompany.com # \u2b07 REQUIRED smarthost: smtp.qiye.aliyun.com:465 require_tls: false hello: yourcompany.com # \u2b06 REQUIRED auth_username: name@yourcompany.com auth_identity: name@yourcompany.com auth_password: ... Reference  https:\/\/github.com\/prometheus\/alertmanager\/issues\/980\uff08\u96be\u4ee5\u5165\u76ee\u7684\u82f1\u6587\uff09 http:\/\/mailhelp.mxhichina.com\/smartmail\/detail.vm?knoId=5871700 ","permalink":"https:\/\/wi1dcard.dev\/posts\/alertmanager-smtp-setup-for-alibaba-mail-service\/","summary":"<p>\u963f\u91cc\u4e91\u6536\u8d2d\u4e07\u7f51\u4e4b\u540e\uff0c\u51e0\u4e4e\u4e0d\u8d5a\u94b1\u7684\u90ae\u4ef6\u670d\u52a1\u8fd8\u771f\u662f\u4e0d\u7ef4\u62a4\u4e0d\u8fed\u4ee3\u4e86 \u2014 \u4e0d\u652f\u6301 DKIM\uff0c\u6ca1\u6cd5\u914d DMARC\uff0c\u5c31\u8fde SMTP \u4e5f\u4e0d\u652f\u6301 STARTTLS 587 \u7aef\u53e3\u3002<\/p>","title":"Alertmanager \u901a\u8fc7\u963f\u91cc\u4e91\u4f01\u4e1a\u90ae\u4ef6 SMTP \u670d\u52a1\u53d1\u4fe1"},{"content":"While I deploying v2ray-exporter with Kustomize, I realized that commonLabels in kustomization.yaml doesn&rsquo;t take care of the spec.selector.matchLabels field in ServiceMonitors. That makes sense, as ServiceMonitor is a part of CoreOS&rsquo;s Prometheus Operator project, neither included nor maintained by Kubernetes. But how can we direct Kustomize to fill the labels in ServiceMonitors or even any fields in customized resources?\nTL;DR kustomization.yaml:\napiVersion: kustomize.config.k8s.io\/v1beta1 kind: Kustomization resources: - servicemonitor.yaml # ... configurations: - ..\/kustomize-configurations\/servicemonitor-matchlabels.yaml commonLabels: app: example-exporter ..\/kustomize-configurations\/servicemonitor-matchlabels.yaml:\ncommonLabels: - path: spec\/selector\/matchLabels create: true group: monitoring.coreos.com kind: ServiceMonitor It seems to me really easy to get confused with commonLabels in Kustomize configuration files or kustomization.yaml. The name commonLabels exists in both of them, but the definitions are totally different.\nservicemonitor.yaml:\napiVersion: monitoring.coreos.com\/v1 kind: ServiceMonitor metadata: name: example-exporter spec: endpoints: - port: http path: \/scrape Results:\napiVersion: monitoring.coreos.com\/v1 kind: ServiceMonitor metadata: labels: app: example-exporter # &lt;-- Here commonLabels originally handles name: example-exporter spec: endpoints: - path: \/scrape port: http selector: matchLabels: app: example-exporter # &lt;-- Here we added labels from commonLabels References  https:\/\/kubectl.docs.kubernetes.io\/pages\/reference\/kustomize.html#configurations ","permalink":"https:\/\/wi1dcard.dev\/posts\/integrate-servicemonitor-matchlabels-with-kustomize-commonlabels\/","summary":"<p>While I deploying <a href=\"https:\/\/github.com\/wi1dcard\/v2ray-exporter\" target=\"_blank\">v2ray-exporter<\/a> with <a href=\"https:\/\/kustomize.io\/\" target=\"_blank\">Kustomize<\/a>, I realized that <code>commonLabels<\/code> in <code>kustomization.yaml<\/code> doesn&rsquo;t take care of the <code>spec.selector.matchLabels<\/code> field in <code>ServiceMonitor<\/code>s. That makes sense, as ServiceMonitor is a part of CoreOS&rsquo;s Prometheus Operator project, neither included nor maintained by Kubernetes. But how can we direct Kustomize to fill the labels in ServiceMonitors or even any fields in customized resources?<\/p>","title":"Integrate ServiceMonitor matchLabels with Kustomize commonLabels"},{"content":"The official doc of OpenWrt on VMware HowTo seems already outdated, and there&rsquo;s no explaination of how to fix Unsupported or invalid disk type 2 for 'scsi0:0'. Ensure that the disk has been imported. on ESXi 6.7. Here after looked into some clues on Chinese router forums, I found an usable method to convert the image into ESXi VMDK format on macOS.\nDownload the Image You can find the .img.gz files on https:\/\/downloads.openwrt.org\/, for example:\nhttps:\/\/downloads.openwrt.org\/releases\/19.07.4\/targets\/x86\/64\/openwrt-19.07.4-x86-64-combined-ext4.img.gz\nInstall Dependencies brew install gzip # To un-gzip .gz files brew install qemu # To convert images Convert .img to .vmdk gunzip openwrt-19.07.4-x86-64-combined-ext4.img.gz qemu-img convert -f raw -O vmdk openwrt-19.07.4-x86-64-combined-ext4.img openwrt-19.07.4-x86-64-combined-ext4.vmdk Upload the VMDK to ESXi You can either upload the image using scp command or via web UI. However, I would suggest enable SSH on your ESXi host and use scp, as the next step requires shell prompt on the host.\nscp openwrt-19.07.4-x86-64-combined-ext4.vmdk root@esxi:\/vmfs\/volumes\/datastore1\/ Fix Unsupported or invalid disk type 2 for 'scsi0:0' Before using the .vmdk file as an &ldquo;existing hard disk&rdquo; on ESXi, there&rsquo;s one more step to convert it into supported disk type.\nssh root@esxi cd \/vmfs\/volumes\/datastore1\/ vmkfstools -i &#39;openwrt-19.07.4-x86-64-combined-ext4.vmdk&#39; openwrt-converted.vmdk -d thin Done! Now we can create and boot a VM with adding openwrt-converted.vmdk as the primary disk. Enjoy it!\n","permalink":"https:\/\/wi1dcard.dev\/posts\/convert-openwrt-image-to-esxi-vmdk\/","summary":"<p>The official doc of <a href=\"https:\/\/openwrt.org\/docs\/guide-user\/virtualization\/vmware\" target=\"_blank\">OpenWrt on VMware HowTo<\/a> seems already outdated, and there&rsquo;s no explaination of how to fix <code>Unsupported or invalid disk type 2 for 'scsi0:0'. Ensure that the disk has been imported.<\/code> on ESXi 6.7. Here after looked into some clues on Chinese router forums, I found an usable method to convert the image into ESXi VMDK format on macOS.<\/p>","title":"Convert OpenWrt Image to ESXi VMDK"},{"content":"\u6700\u8fd1\u5728\u63a2\u7d22\u300c\u5982\u4f55\u53d1\u5e03 NPM \u5305\u300d\u7684\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u591a\u6570\u4eba\u7684\u601d\u8def\u8981\u4e48\u5b8c\u5168\u4e0d\u7528 CI\uff0c\u4fee\u6539 package.json \u5185\u7248\u672c\u53f7\u4e4b\u540e\u624b\u52a8\u53d1\u5e03\uff1b\u8981\u4e48\u7ed3\u5408 CI\uff0c\u4f46\u9700\u8981 CI \u751f\u6210\u65b0\u7248\u672c\u53f7\u4e4b\u540e\u4fee\u6539 package.json\uff0c\u6700\u540e\u673a\u5668\u4eba\u6267\u884c Git Commit + Git Tag \u5e76\u63a8\u9001\u5230\u4ed3\u5e93\u5185\u3002\u8fd9\u4e24\u79cd\u505a\u6cd5\u6211\u90fd\u4e0d\u662f\u5f88\u559c\u6b22\uff0c\u524d\u8005\u6ca1\u6709 CI \u4e0d\u80fd\u5fcd\uff0c\u540e\u8005\u4e0d\u4ec5\u8981\u6c42 CI \u6709\u5199\u6743\u9650\uff0c\u800c\u4e14\u4f1a\u4ed3\u5e93\u5185\u589e\u52a0\u8bb8\u591a\u5f62\u5982 Release v... \u4e4b\u7c7b\u7684\u63d0\u4ea4\uff0c\u5f3a\u8feb\u75c7\u8868\u793a\u63a5\u53d7\u4e0d\u4e86\u3002\n\u4e0d\u8fc7\u7ecf\u8fc7\u4e00\u756a\u7814\u7a76\uff0c\u6211\u8fd8\u662f\u627e\u5230\u4e86\u4e24\u79cd\u6bd4\u8f83\u300c\u5e72\u51c0\u300d\u7684\u601d\u8def\uff0c\u6765\u770b\u770b\u5427\u3002\n\u65b9\u6cd5 1 \u8fd9\u79cd\u65b9\u6cd5\u4e0e\u4e0a\u6587\u4e2d\u63d0\u5230\u7684\u601d\u8def\u7c7b\u4f3c\uff0c\u53ea\u662f\u539f\u5148\u7684 4 \u4e2a\u6b65\u9aa4\uff1a\n \u6839\u636e Changelog \u751f\u6210\u65b0\u7248\u672c\u53f7\u3002 \u4fee\u6539 package.json \u7684 versison \u5b57\u6bb5\u3002 \u6267\u884c npm publish\u3002 \u6267\u884c git commit\u3001git tag\u3001git push\u3002  \u88ab\u7f29\u51cf\u5230\u4e86 2 \u6b65\uff1a\n \u6839\u636e CI \u63d0\u4f9b\u7684\u73af\u5883\u53d8\u91cf\uff0c\u62ff\u5230\u89e6\u53d1\u5f53\u524d CI Job \u7684 Tag \u540d\u79f0\uff0c\u636e\u6b64\u4fee\u6539 package.json \u7684 versison \u5b57\u6bb5\u3002 \u6267\u884c npm publish\u3002  \u53e6\u5916\u89e6\u53d1\u7684\u6761\u4ef6\u4ece On Push \u6362\u6210\u4e86 On Push Tags\u3002\n\u5bf9\u4e8e GitHub Actions\uff0c\u53ef\u4ee5\u4f7f\u7528 Shell parameter expansion \u62ff\u5230 Tag \u540d\u79f0\uff1a\nexport GIT_TAG_NAME=${GITHUB_REF\/refs\\\/tags\\\/\/} npm version --allow-same-version=true --git-tag-version=false &#34;$GIT_TAG_NAME&#34; \u65b9\u6cd5 2 \u8fd9\u79cd\u65b9\u6cd5\u4ecd\u7136\u662f CI \u521b\u5efa Tag\uff0c\u53ea\u7701\u6389\u4e86 Commit\uff1a\n \u5f00\u53d1\u8005\u4fee\u6539 package.json \u5185\u7684\u7248\u672c\u53f7\u5e76\u63d0\u4ea4\u3002 CI \u68c0\u67e5\u662f\u5426\u6709\u5fc5\u8981\u53d1\u5e03\u65b0\u7248\u672c\uff0c\u4f8b\u5982\u53ef\u4ee5\uff1a  \u68c0\u67e5\u5f53\u524d\u7248\u672c\u662f\u5426\u4e0d\u5b58\u5728\uff0c\u4f8b\u5982\u6267\u884c test -z &quot;$(npm view .@&lt;VERSION&gt;)&quot;\u3002 \u68c0\u67e5 Commit Message \u662f\u5426\u5305\u542b\u5173\u952e\u8bcd\uff0c\u4f8b\u5982 Release *\u3002   \u6267\u884c npm publish\u3002 \u6267\u884c git tag\u3001git push --tags\u3002  \u53c2\u8003  \u65b9\u6cd5 1\uff1ahttps:\/\/github.com\/mikeal\/merge-release \u65b9\u6cd5 2\uff1ahttps:\/\/github.com\/marketplace\/actions\/publish-to-npm https:\/\/github.community\/t\/how-to-get-just-the-tag-name\/16241  \u788e\u788e\u5ff5 \u4e0d\u592a\u7406\u89e3 NPM \u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u505a\uff0c\u52a0\u4e2a npm publish --version=... \u4f3c\u4e4e\u5b8c\u7f8e\u89e3\u51b3\u95ee\u9898\u3002\u6211\u731c\u5927\u6982\u662f\u5386\u53f2\u539f\u56e0\uff0c\u53ef\u80fd\u90a3\u4e2a\u5e74\u4ee3\u8fd8\u6ca1\u4ec0\u4e48\u4eba\u7528 CI \u548c Git Tag\uff0c\u66f4\u6d41\u884c\u7528\u6587\u4ef6\u6765\u7ba1\u7406\u7248\u672c\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/npm-publish-with-git-tag-and-ci-cd\/","summary":"<p>\u6700\u8fd1\u5728\u63a2\u7d22\u300c\u5982\u4f55\u53d1\u5e03 NPM \u5305\u300d\u7684\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u591a\u6570\u4eba\u7684\u601d\u8def\u8981\u4e48\u5b8c\u5168\u4e0d\u7528 CI\uff0c\u4fee\u6539 <code>package.json<\/code> \u5185\u7248\u672c\u53f7\u4e4b\u540e\u624b\u52a8\u53d1\u5e03\uff1b\u8981\u4e48\u7ed3\u5408 CI\uff0c\u4f46\u9700\u8981 CI \u751f\u6210\u65b0\u7248\u672c\u53f7\u4e4b\u540e\u4fee\u6539 <code>package.json<\/code>\uff0c\u6700\u540e\u673a\u5668\u4eba\u6267\u884c Git Commit + Git Tag \u5e76\u63a8\u9001\u5230\u4ed3\u5e93\u5185\u3002\u8fd9\u4e24\u79cd\u505a\u6cd5\u6211\u90fd\u4e0d\u662f\u5f88\u559c\u6b22\uff0c\u524d\u8005\u6ca1\u6709 CI \u4e0d\u80fd\u5fcd\uff0c\u540e\u8005\u4e0d\u4ec5\u8981\u6c42 CI \u6709\u5199\u6743\u9650\uff0c\u800c\u4e14\u4f1a\u4ed3\u5e93\u5185\u589e\u52a0\u8bb8\u591a\u5f62\u5982 <code>Release v...<\/code> \u4e4b\u7c7b\u7684\u63d0\u4ea4\uff0c\u5f3a\u8feb\u75c7\u8868\u793a\u63a5\u53d7\u4e0d\u4e86\u3002<\/p>\n<p>\u4e0d\u8fc7\u7ecf\u8fc7\u4e00\u756a\u7814\u7a76\uff0c\u6211\u8fd8\u662f\u627e\u5230\u4e86\u4e24\u79cd\u6bd4\u8f83\u300c\u5e72\u51c0\u300d\u7684\u601d\u8def\uff0c\u6765\u770b\u770b\u5427\u3002<\/p>","title":"\u4f7f\u7528 Git Tag \u548c CI \u5e72\u51c0\u5730\u53d1\u5e03 NPM \u5305"},{"content":"As you probably heard Terraform before, it&rsquo;s a great DevOps tool that can help you build your infrastructures with configurations and codes, aka Infrastructure as Code.\nTerraform has a bunch of great integrations with cloud platforms, some of them are maintained by Terraform official, such as Azure provider and AWS provider. However, Alibaba Cloud (which is the biggest public cloud company in China mainland) provider is created and maintained by alibaba itself so far. Lack of quick start guide and documentation makes it a little bit hard to get started with.\nTherefore, this blog here might help you take a quick tour of Alibaba Cloud provider and launch an instance from zero with the VPC, switches and security groups along. I&rsquo;ll list the reference docs I can find as much as possible. Let&rsquo;s begin!\nPreparation Create main.tf to store your infra config files in any directory you prefer. However, I recommend placing the file in a git repo.\nterraform {# Terraform related configs  backend &#34;local&#34; {# We use local backend to keep it simple  path = &#34;terraform.tfstate&#34;# The file where the Terraform states stores in  } } provider &#34;alicloud&#34; {# Here you can find the &#34;Region ID&#34;: https:\/\/www.alibabacloud.com\/help\/doc-detail\/40654.htm  region = &#34;cn-beijing&#34;# How to create a pair of access_key and secret_key: https:\/\/www.alibabacloud.com\/help\/doc-detail\/53045.htm  access_key = &#34;...&#34; secret_key = &#34;...&#34; }# Some useful variables to reduce copy-paste, you can add whatever you like locals { prefix = &#34;foo&#34; domain = &#34;wi1dcard.dev&#34; hostname = &#34;${local.prefix}.${local.domain}&#34; zone = &#34;cn-beijing-h&#34; } Network Setup Before creating an ECS instance, let&rsquo;s have a look at the network related resources.\nresource &#34;alicloud_vpc&#34; &#34;default&#34; {# Here we used the variables in the `locals` section above  name = local.prefix# Set the CIDR for this VPC  cidr_block = &#34;192.168.200.0\/24&#34; } resource &#34;alicloud_vswitch&#34; &#34;default&#34; {# Use the VPC&#39;s ID  vpc_id = alicloud_vpc.default.id# Set the CIDR for this switch, must be in the CIDR of the VPC  cidr_block = &#34;192.168.200.0\/24&#34;# As the VPC is a region-specified resource, switches are for zones  availability_zone = local.zone } The VPC and switches are both necessary, Alibaba Cloud doesn&rsquo;t allow you to create an instance without the private network and the instance must be connected to a switch.\nYou can also set up more switches, if you&rsquo;d like to have your instances across multiple zones.\nThe next step is to create the security group and its rules in order to allow public network access.\nresource &#34;alicloud_security_group&#34; &#34;default&#34; { name = local.prefix vpc_id = alicloud_vpc.default.id# Allow instances in the same security group reaching each other  inner_access_policy = &#34;Accept&#34; } resource &#34;alicloud_security_group_rule&#34; &#34;allow_ssh&#34; {# Refer the security group ID  security_group_id = alicloud_security_group.default.id type = &#34;ingress&#34; ip_protocol = &#34;tcp&#34;# Since the security group is for using in the VPC, you need to set it to intranet: https:\/\/www.terraform.io\/docs\/providers\/alicloud\/r\/security_group_rule.html  nic_type = &#34;intranet&#34; policy = &#34;accept&#34; cidr_ip = &#34;0.0.0.0\/0&#34; port_range = &#34;22\/22&#34; } resource &#34;alicloud_security_group_rule&#34; &#34;allow_icmp&#34; { security_group_id = alicloud_security_group.default.id type = &#34;ingress&#34; ip_protocol = &#34;icmp&#34; nic_type = &#34;intranet&#34; policy = &#34;accept&#34; cidr_ip = &#34;0.0.0.0\/0&#34; } Here I had 1 security group and 2 security group rules. I usually bind only one security group to every instance. However, it&rsquo;s okay if you bind multiple ones.\nSSH Authentication Setup To enable you logging in the instances you&rsquo;ve launched with SSH, we&rsquo;d have to create an SSH key pair, or you will need to go to the web console and reset the root password.\nresource &#34;alicloud_key_pair&#34; &#34;default&#34; { key_name = local.prefix public_key = &#34;ssh-rsa ... wi1dcard@wi1dcard.dev&#34; } To be noticed, both the key pairs along with other resources we just created are region-specified. if you changed the default region setting in the provider &quot;alicloud&quot; section, it is required to recreate the resources:\nprovider &#34;alicloud&#34; { region = &#34;cn-shanghai&#34;# For example, if you changed your primary region to Shanghai } ECS Instance resource &#34;alicloud_instance&#34; &#34;default&#34; {# You can enable `dry_run` and run `terraform apply` to call the Alibaba Cloud API but not really create an instance  dry_run = false instance_name = local.hostname# Refer to local variables  host_name = local.hostname key_name = alicloud_key_pair.default.key_name# Refer to the key pair name  vswitch_id = alicloud_vswitch.default.id# Refer to the vswitch ID  security_groups = [alicloud_security_group.default.id]# The security groups associated to the instance # Check out the whole list of the instance types: https:\/\/www.alibabacloud.com\/help\/doc-detail\/25378.htm # We use the cheapest instance type (I found so far) for testing  instance_type = &#34;ecs.s6-c1m1.small&#34; instance_charge_type = &#34;PostPaid&#34;# Of course post paid!  credit_specification = &#34;Standard&#34; spot_strategy = &#34;NoSpot&#34;# You can find the image IDs on https:\/\/ecs.console.aliyun.com\/ &gt; Instances &amp; Images &gt; Images &gt; Public Image  image_id = &#34;ubuntu_18_04_x64_20G_alibase_20191225.vhd&#34; system_disk_category = &#34;cloud_efficiency&#34; system_disk_size = 20# Disable the useless &#34;security enhancement&#34; features  security_enhancement_strategy = &#34;Deactive&#34; internet_max_bandwidth_in = 100 internet_max_bandwidth_out = 100 internet_charge_type = &#34;PayByTraffic&#34;# Of course pay by traffic!! } While the first time I tried to launch an instance, the most significant problem I found is how to find the correct image ID. Fortunately, Alibaba Cloud maintains a CLI tool called &lt;code&gt;aliyun-cli&lt;\/code&gt; (aliyun is the Chinese pinyin of the word alibabacloud) and there&rsquo;s an API DescribeImage for listing all the images.\nBut it doesn&rsquo;t work as expected, so far I found 2 issues - it shows no image if I didn&amp;rsquo;t put in a specific parameter and either the --ImageID or --Filter.n.Key doesn&rsquo;t support fuzzy matching. That means even though the first issue will get resolved, the later doesn&rsquo;t allow users to search the image by specifying a keyword like ubuntu.\nWell, just forget about the Aliyun CLI, let&rsquo;s use web console once and for all though&hellip;\nDNS Records (Optional) We&rsquo;ve got all resources prepared. However, the public IP of the instance could be randomly associated. This means every time you terminate the instance and relaunch a new one, the IP will get changed. Therefore, it&rsquo;s also recommended to add a DNS record pointing to the instance.\nresource &#34;alicloud_dns_record&#34; &#34;default&#34; { name = local.domain host_record = local.prefix type = &#34;A&#34; ttl = 600 routing = &#34;default&#34;# Refer to the public IP of the instance  value = alicloud_instance.default.public_ip } You can also try add an output variable without setting up NS servers.\noutput &#34;public_ip&#34; { value = alicloud_instance.default.public_ip } Apply the plans Time to apply all these configs and plans! All we need to do is:\nterraform apply  An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: ... Plan: 9 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes alicloud_vpc.default: Creating... alicloud_key_pair.default: Creating... alicloud_key_pair.default: Creation complete after 1s [id=dummy] alicloud_vpc.default: Creation complete after 8s [id=vpc-2zey1j4f97ftg3zt1n5x6] ... Apply complete! Resources: 9 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate Outputs: public_ip = 123.57.**.** That&rsquo;s all!\nReferences Please see also:\n Alibabcloud - How do I specify images for ECS resources? Terraform Output Command Terraform Alibaba Cloud Provider Documentation ","permalink":"https:\/\/wi1dcard.dev\/posts\/terraform-quick-start-with-alibabacloud\/","summary":"<p>As you probably heard Terraform before, it&rsquo;s a great DevOps tool that can help you build your infrastructures with configurations and codes, aka Infrastructure as Code.<\/p>\n<p>Terraform has a bunch of great integrations with cloud platforms, some of them are maintained by Terraform official, such as Azure provider and AWS provider. However, Alibaba Cloud (which is the biggest public cloud company in China mainland) provider is created and maintained by alibaba itself so far. Lack of quick start guide and documentation makes it a little bit hard to get started with.<\/p>","title":"Terraform Quick Start with Alibaba Cloud"},{"content":"\u5df2\u53d1\u5e03\u7684  DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 - \u5b9a\u65f6\u4efb\u52a1\u76d1\u63a7\u7684\u8fdb\u5316\u4e4b\u8def \u4e00\u6b21 KubeCPUOvercommit \u544a\u8b66\u6392\u67e5\u8fc7\u7a0b\u5c0f\u8bb0 DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 \u2014 \u5728 K8s \u4e0a\u81ea\u52a8\u5316\u6267\u884c Database Migration \u57fa\u4e8e UniFi \u5168\u5bb6\u6876\u7684\u4f01\u4e1a Wi-Fi \u5ba2\u6237\u7aef\u7ba1\u7406 DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 \u2014 \u7ba1\u7406 Incident \u5de5\u4f5c\u6d41  \u8fc1\u79fb\u81f3\u4e2a\u4eba\u535a\u5ba2\u7684 \u7531\u4e8e\u76f8\u5173\u4eba\u5458\u957f\u671f\u62d6\u5ef6\u5ba1\u7a3f\u3001\u53d1\u7a3f\uff0c\u5c06\u90e8\u5206\u6587\u7ae0\u8fc1\u79fb\u81f3\u4e2a\u4eba\u535a\u5ba2\u53d1\u5e03\u3002\n \u642d\u5efa\u5f02\u6784 CPU \u7ec4\u6210\u7684\u8fb9\u7f18\u8ba1\u7b97 Kubernetes \u96c6\u7fa4 \u8de8\u9879\u76ee GitLab CI \u914d\u7f6e\u590d\u7528\u4e0e\u7ba1\u7406 K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u4e86\u89e3 Helm K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u4e86\u89e3 Helmfile K8s \u4e0b\u7684 TLS \u8bc1\u4e66\u7ba1\u7406 \u2014 \u4e86\u89e3 Cert-Manager \u521b\u5efa\u5e76\u7ef4\u62a4\u5546\u4e1a\u9879\u76ee\u7684 Helm Chart \u76d8\u70b9\u4f7f macOS \u5e94\u7528\u6d41\u91cf\u901a\u8fc7\u4ee3\u7406\u7684\u591a\u79cd\u65b9\u5f0f  \u5df2\u8fc7\u5ba1\u5f85\u53d1\u5e03\u7684  \u4f7f\u7528 Prometheus \u76d1\u63a7\u7f51\u7edc\u53ef\u7528\u6027  \u6b22\u8fce\u6301\u7eed\u5173\u6ce8 RightCapital \u6280\u672f\u56e2\u961f\u516c\u4f17\u53f7\uff1a\n","permalink":"https:\/\/wi1dcard.dev\/posts\/rightcapital-blog-posts-composed-by-me\/","summary":"\u5df2\u53d1\u5e03\u7684  DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 - \u5b9a\u65f6\u4efb\u52a1\u76d1\u63a7\u7684\u8fdb\u5316\u4e4b\u8def \u4e00\u6b21 KubeCPUOvercommit \u544a\u8b66\u6392\u67e5\u8fc7\u7a0b\u5c0f\u8bb0 DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 \u2014 \u5728 K8s \u4e0a\u81ea\u52a8\u5316\u6267\u884c Database Migration \u57fa\u4e8e UniFi \u5168\u5bb6\u6876\u7684\u4f01\u4e1a Wi-Fi \u5ba2\u6237\u7aef\u7ba1\u7406 DevOps \u81ea\u52a8\u5316\u5b9e\u8df5 \u2014 \u7ba1\u7406 Incident \u5de5\u4f5c\u6d41  \u8fc1\u79fb\u81f3\u4e2a\u4eba\u535a\u5ba2\u7684 \u7531\u4e8e\u76f8\u5173\u4eba\u5458\u957f\u671f\u62d6\u5ef6\u5ba1\u7a3f\u3001\u53d1\u7a3f\uff0c\u5c06\u90e8\u5206\u6587\u7ae0\u8fc1\u79fb\u81f3\u4e2a\u4eba\u535a\u5ba2\u53d1\u5e03\u3002","title":"\u6211\u64b0\u5199\u7684 RightCapital \u6280\u672f\u535a\u5ba2\u6587\u7ae0\u94fe\u63a5"},{"content":"\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u7ecf\u5e38\u9700\u8981\u4f7f\u7528\u5230\u56fd\u5916\u7684\u8d44\u6e90\uff0c\u4f8b\u5982\u5404\u79cd\u5305\u4f9d\u8d56\u7b49\u3002\u56fd\u5185\u76ee\u524d\u6bd4\u8f83\u666e\u904d\u7684\u505a\u6cd5\u662f\u4f7f\u7528\u7531\u77e5\u540d\u7b2c\u4e09\u65b9\u7ef4\u62a4\u7684\u56fd\u5185\u955c\u50cf\u3002\u867d\u7136\u65b9\u4fbf\uff0c\u4f46\u4e5f\u5b58\u5728\u4e00\u4e9b\u65e0\u6cd5\u907f\u514d\u7684\u95ee\u9898\uff0c\u4f8b\u5982\uff1a\n \u955c\u50cf\u53ef\u9760\u6027\u672a\u77e5\uff0c\u51fa\u95ee\u9898\u65f6\u6211\u4eec\u65e0\u80fd\u4e3a\u529b\uff0c\u53ea\u80fd\u7b49\u5f85\u7b2c\u4e09\u65b9\u4fee\u590d\u3002 \u955c\u50cf\u540c\u6b65\u65f6\u95f4\u672a\u77e5\uff0c\u53ef\u80fd\u5b58\u5728\u6570\u636e\u6ede\u540e\u3002 \u5b58\u5728\u5b89\u5168\u9690\u60a3\uff08\u5c3d\u7ba1\u53ef\u80fd\u6027\u8f83\u5c0f\uff09\u3002  \u56e0\u6b64\uff0c\u6211\u4e2a\u4eba\u66f4\u52a0\u63a8\u8350\u4f9d\u8d56\u4ee3\u7406\u6765\u5b9e\u73b0\u5feb\u901f\u8bbf\u95ee\u6240\u9700\u8d44\u6e90\u7684\u76ee\u7684\u3002\u672c\u6587\u4e0d\u4f1a\u6d89\u53ca\u4efb\u4f55\u8fdd\u53cd\u6cd5\u5f8b\u6cd5\u89c4\u7684\u5185\u5bb9\uff0c\u53ea\u6765\u8c08\u8c08 macOS \u4e0b\u5982\u4f55\u8ba9\u4e0d\u540c\u5e94\u7528\u7684\u6d41\u91cf\u901a\u8fc7 \u672c\u5730\u7684 \u4ee3\u7406\u670d\u52a1\u3002\n\u5728\u5f00\u59cb\u524d\uff0c\u6211\u5c06\u5047\u8bbe\u4f60\u5df2\u7ecf\u5728\u672c\u5730\u914d\u7f6e\u597d\u4e86 HTTP \u548c SOCKS5 \u4ee3\u7406\u670d\u52a1\uff0c\u5206\u522b\u80fd\u591f\u901a\u8fc7 http:\/\/127.0.0.1:8080 \u548c socks5:\/\/127.0.0.1:1080 \u8bbf\u95ee\u3002\n\u7cfb\u7edf\u4ee3\u7406 \u4f5c\u4e3a macOS \u5185\u7f6e\u7684\u529f\u80fd\uff0c\u4f60\u53ef\u4ee5\u5728 System Preferences -&gt; Network -&gt; Advanced -&gt; Proxies \u5185\u914d\u7f6e\u7cfb\u7edf\u4ee3\u7406\u3002\n\u53e6\u5916\u4e5f\u53ef\u4ee5\u4f7f\u7528\u547d\u4ee4\u884c\u914d\u7f6e\u7cfb\u7edf\u4ee3\u7406\uff1a\nnetworksetup -setwebproxy &#34;Wi-Fi&#34; 127.0.0.1 8080 # HTTP proxy networksetup -setsocksfirewallproxy &#34;Wi-Fi&#34; 127.0.0.1 1080 # SOCKS5 proxy networksetup -setwebproxystate &#34;Wi-Fi&#34; on networksetup -setsocksfirewallproxystate &#34;Wi-Fi&#34; on \u5176\u4e2d &quot;Wi-Fi&quot; \u662f\u4f60\u7684\u7f51\u7edc\u63a5\u53e3\u540d\uff0c\u8bf7\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u586b\u5199\u3002\n\u4e0d\u8fc7\uff0cmacOS \u7684\u7cfb\u7edf\u4ee3\u7406\u4ec5\u5bf9\u90e8\u5206 GUI \u6216\u505a\u4e86 macOS \u9002\u914d\u7684\u5e94\u7528\u751f\u6548\uff0c\u4f8b\u5982 Chrome \u7b49 Web \u6d4f\u89c8\u5668\u3001\u7cfb\u7edf\u66f4\u65b0\u7b49\u3002\u5728\u5f00\u53d1\u65f6\u6211\u4eec\u7ecf\u5e38\u9700\u8981\u63a5\u89e6 CLI\uff0c\u5e94\u8be5\u600e\u4e48\u505a\u5462\uff1f\nhttp_proxy \u548c all_proxy \u73af\u5883\u53d8\u91cf \u7edd\u5927\u591a\u6570\u4f7f\u7528 HTTP \u534f\u8bae\u7684 CLI \u5e94\u7528\u90fd\u652f\u6301\u8fd9\u4e24\u4e2a\u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u51e0\u4e4e\u5df2\u7ecf\u6210\u4e3a\u4e86\u300c\u884c\u4e1a\u6807\u51c6\u300d\uff1a\nexport http_proxy=http:\/\/127.0.0.1:8080 https_proxy=$http_proxy all_proxy=socks5:\/\/127.0.0.1:1080 \u5178\u578b\u652f\u6301\u7684\u547d\u4ee4\u5305\u62ec curl\u3001go get\u3001composer install \u7b49\u3002\u4f7f\u7528 curl -v ipinfo.io \u67e5\u770b\u8f93\u51fa\u53ef\u53d1\u73b0\u4ee3\u7406\u914d\u7f6e\u5df2\u7ecf\u751f\u6548\uff1a\n* Uses proxy env variable http_proxy == &#39;http:\/\/127.0.0.1:8080&#39; * Trying 127.0.0.1... ... \u5982\u679c\u4f60\u672c\u5730\u7684\u4ee3\u7406\u670d\u52a1\u5e38\u9a7b\u540e\u53f0\u8fd0\u884c\uff0c\u53ef\u5c06 export ... \u547d\u4ee4\u5199\u5165 .zshrc\uff0c\u8fd9\u6837\u6bcf\u6b21\u542f\u52a8 Zsh\uff08Shell\uff09\u65f6\u5c31\u81ea\u52a8\u914d\u7f6e\u597d\u4e86\u3002\nSSH Config ProxyCommand \u6307\u4ee4 \u50cf Git over SSH\u3001SCP\u3001SFTP \u8fd9\u7c7b\u57fa\u4e8e SSH \u534f\u8bae\u7684\u5e94\u7528\uff0c\u5e76\u4e0d\u652f\u6301\u4ee5\u4e0a\u4e24\u4e2a\u73af\u5883\u53d8\u91cf\u3002\u4e0d\u8fc7\u6211\u4eec\u53ef\u4ee5\u4fee\u6539 SSH \u914d\u7f6e\u6587\u4ef6 ~\/.ssh\/config \u6765\u5b9e\u73b0\uff0c\u4f8b\u5982\uff1a\nHost github.com ProxyCommand \/usr\/bin\/nc -x 127.0.0.1:1080 %h %p \u4ee5\u4e0a\u914d\u7f6e\u4e2d\u7684 ProxyCommand \u53ea\u5728\u8fde\u63a5\u5230 github.com \u65f6\u751f\u6548\uff0c\u4f60\u53ef\u4ee5\u5c06 Host github.com \u66ff\u6362\u6210\u5176\u5b83 Git \u670d\u52a1\u5546\u7684\u4e3b\u673a\u540d\uff0c\u4e5f\u53ef\u4ee5\u66ff\u6362\u4e3a Host *\uff0c\u8868\u793a SSH \u5230\u4efb\u610f\u4e3b\u673a\u5747\u751f\u6548\u3002\u4f46\u6211\u5e76\u4e0d\u63a8\u8350\u8fd9\u4e48\u505a\uff0c\u9664\u975e\u4f60\u60f3 SSH \u5230\u81ea\u5df1\u7684\u670d\u52a1\u5668\u65f6\u4e5f\u901a\u8fc7\u4ee3\u7406\u3002\nProxifier \u548c Surge \u6839\u636e\u6211\u81ea\u5df1\u7684\u7ecf\u9a8c\uff0c\u4ee5\u4e0a\u65b9\u6cd5\u5df2\u7ecf\u80fd\u591f\u8986\u76d6\u7edd\u5927\u591a\u6570\u5f00\u53d1\u8005\u7684\u4f7f\u7528\u573a\u666f\u3002\u5982\u679c\u6709\u4e9b\u5e94\u7528\u8fd8\u662f\u4e0d\u8d70\u4ee3\u7406\uff0c\u4f60\u53ef\u4ee5\u8bd5\u8bd5 Proxifier \u548c Surge \u8fd9\u4e24\u6b3e\u4ea7\u54c1\u3002\u5176\u4e2d Surge \u662f macOS \u4e13\u6709\u5e94\u7528\uff0c\u4e0d\u53ef\u7528\u4e8e Windows \u6216 Linux \u7cfb\u7edf\u3002\u8fd9\u7c7b\u5e94\u7528\u7684\u601d\u8def\u5927\u81f4\u662f\uff1a\n \u4f2a\u88c5\u6210 TUN \u8bbe\u5907\uff08\u53ef\u7406\u89e3\u4e3a\u865a\u62df\u7f51\u5361\uff09\u3002 \u4fee\u6539\u6216\u8986\u76d6\u7cfb\u7edf\u9ed8\u8ba4\u8def\u7531\uff0c\u628a\u6240\u6709 TCP\u3001UDP\u3001ICMP \u7b49\u4e09\u5c42\u53ca\u4ee5\u4e0a\u7684\u6d41\u91cf\u5168\u90e8\u53d1\u5230\u865a\u62df TUN \u8bbe\u5907\u3002 \u7ecf\u8fc7\u5185\u90e8\u5904\u7406\u540e\u628a\u6d41\u91cf\u5bfc\u5411\u4ee3\u7406\u670d\u52a1\u3002 \u4ee3\u7406\u670d\u52a1\u5668\u6d41\u51fa\u7684\u6d41\u91cf\u4f7f\u7528 SO_MARK \u7b49\u65b9\u5f0f\u8fdb\u884c\u7279\u6b8a\u6807\u8bb0\uff0c\u4f7f\u7528\u7cfb\u7edf\u7b56\u7565\u8def\u7531\u5bfc\u5411\u5230\u771f\u5b9e\u7f51\u5361\uff0c\u907f\u514d\u6b7b\u5faa\u73af\u3002  \u4f8b\u5982\u542f\u52a8 Surge \u589e\u5f3a\u6a21\u5f0f\u540e\uff0c\u53ef\u4f7f\u7528 netstat -nr \u770b\u51fa\u8def\u7531\u8868\u7684\u53d8\u5316\uff1a\nRouting tables Internet: Destination Gateway Flags Netif Expire default 192.168.1.254 UGSc en0 &lt;-- \u9ed8\u8ba4\u8def\u7531 1 198.18.0.1 UGSc utun7 &lt;--- 2\/7 198.18.0.1 UGSc utun7 | 4\/6 198.18.0.1 UGSc utun7 | \u4e3a\u4e86\u8986\u76d6\u9ed8\u8ba4\u8def\u7531 8\/5 198.18.0.1 UGSc utun7 | Surge \u65b0\u589e\u7684\u8def\u7531 16\/4 198.18.0.1 UGSc utun7 | 32\/3 198.18.0.1 UGSc utun7 | 64\/2 198.18.0.1 UGSc utun7 &lt;--- ... \u865a\u62df TUN \u8bbe\u5907\u63a5\u53e3\u540d\u4e3a utun7\uff0c\u7f51\u5173 IP \u4e3a 198.18.0.1\uff0c\u8fd9\u4e2a IP \u6bb5\u8fd8\u88ab Surge \u7528\u6765\u505a\u4e00\u4e9b\u7279\u6b8a\u7528\u9014\uff0c\u4f8b\u5982\u53cd\u67e5 IP \u5bf9\u5e94\u7684\u57df\u540d\u4ee5\u652f\u6301\u7b56\u7565\u4ee3\u7406\u529f\u80fd\uff0c\u5728\u6b64\u4e0d\u518d\u8be6\u8ff0\u3002\n\u8fd9\u7c7b\u5b9e\u73b0\u867d\u7136\u7406\u8bba\u4e0a\u80fd\u591f\u5c06\u7cfb\u7edf\u6240\u6709\u6d41\u91cf\u90fd\u5bfc\u5411\u8fd9\u4e2a\u865a\u62df\u7684 TUN \u8bbe\u5907\uff0c\u4f46\u4ecd\u6709\u4e00\u4e9b\u5c40\u9650\u3002\u76ee\u524d\u6839\u636e\u6211\u7684\u89c2\u5bdf\uff0cFaceTime \u4f3c\u4e4e\u4e0d\u4f1a\u9075\u5faa\u8def\u7531\u8868\u7684\u914d\u7f6e\uff0c\u6211\u731c\u662f Apple \u4e3a\u4e86\u4f18\u5316\u901a\u8baf\u534f\u8bae\u76f4\u63a5\u7ed5\u8fc7\u4e86\u81ea\u5b9a\u4e49\u8def\u7531\u8868\u4ee5\u4fbf\u4e8e\u53d1\u8d77\u70b9\u5bf9\u70b9\u901a\u8baf\u5427\u3002\n\u53e6\u5916\uff0c\u7531\u4e8e SOCKS \u548c HTTP \u4ee3\u7406\u534f\u8bae\u7684\u9650\u5236\uff0c\u867d\u7136\u4fee\u6539\u8def\u7531\u8868\u540e ICMP \u6d41\u91cf\u4e5f\u4f1a\u5230\u8fbe\u865a\u62df TUN \u8bbe\u5907\uff0c\u4f46\u5b83\u4e0d\u80fd\u4ee3\u7406 ICMP \u534f\u8bae\uff0c\u56e0\u6b64\u5982\u4f55\u300c\u4f18\u96c5\u5730\u300d\u5904\u7406\u8fd9\u4e9b\u6d41\u91cf\uff0c\u4ecd\u7136\u662f Surge \u8fd9\u7c7b\u4ea7\u54c1\u9700\u8981\u4f18\u5316\u7684\u95ee\u9898\u3002\n\u7efc\u4e0a\uff0c\u6211\u4e2a\u4eba\u4e0d\u7279\u522b\u5e38\u7528 Surge \u7684\u589e\u5f3a\u6a21\u5f0f\uff0c\u4f46\u6709\u65f6\u4e0d\u786e\u5b9a\u67d0\u4e2a\u5e94\u7528\u662f\u5426\u652f\u6301\u901a\u5e38\u7684\u4ee3\u7406\u914d\u7f6e\u3001\u65f6\u95f4\u53c8\u6bd4\u8f83\u7d27\u5f20\u65f6\uff0c\u9b54\u6539\u8def\u7531\u7684\u786e\u662f\u4e2a\u7b80\u5355\u7c97\u66b4\u3001\u5feb\u5200\u65a9\u4e71\u9ebb\u7684\u89e3\u51b3\u65b9\u6848\u3002\n\u901a\u8fc7 LD_PRELOAD \u52ab\u6301\u5171\u4eab\u5e93 \u5229\u7528\u8fd9\u79cd\u65b9\u5f0f\u6700\u597d\u7684\u5f53\u5c5e proxychains-ng \u9879\u76ee\u4e86\uff0c\u5b83\u662f\u4e0a\u53e4\u4e16\u7eaa proxychains \u7684\u7ee7\u4efb\u8005\u3002\n\u4e3b\u8981\u601d\u8def\u662f\u901a\u8fc7\u4fee\u6539 LD_PRELOAD \u73af\u5883\u53d8\u91cf\uff0c\u52ab\u6301 connect() \u7b49\u7cfb\u7edf\u8c03\u7528\uff0c\u4ece\u800c\u5c06\u6d41\u91cf\u8f6c\u53d1\u5230\u4ee3\u7406\u670d\u52a1\u5668\u3002\u7531\u4e8e\u6211\u5bf9\u8fd9\u7c7b\u4ea7\u54c1\u4f7f\u7528\u4e0d\u591a\uff0c\u56e0\u6b64\u4e0d\u591a\u4f5c\u8bc4\u8bba\u3002\u4f46\u6bd4\u8f83\u80af\u5b9a\u7684\u662f\uff0c\u50cf Golang \u9759\u6001\u7f16\u8bd1\u540e\u7684\u5e94\u7528\uff0c\u7531\u4e8e\u5b83\u4eec\u4e0d\u4f1a\u8f7d\u5165\u7cfb\u7edf\u5171\u4eab\u5e93\uff0c\u6240\u4ee5 proxychains-ng \u5bf9\u5176\u65e0\u6548\u3002\n\u901a\u8fc7 ptrace \u8ddf\u8e2a\u7cfb\u7edf\u8c03\u7528 \u4e0e\u4e0a\u4e00\u79cd\u65b9\u6cd5\u7c7b\u4f3c\uff0c\u8be5\u65b9\u6cd5\u7684\u601d\u8def\u4e5f\u662f\u5bf9 connect()\u300c\u505a\u624b\u811a\u300d\uff0c\u53ea\u662f\u4e0d\u901a\u8fc7\u52ab\u6301\u5171\u4eab\u5e93\u5b9e\u73b0\u3002\u53ea\u53ef\u60dc\u76ee\u524d macOS \u4e0a\u7531\u4e8e\u7cfb\u7edf\u5b89\u5168\u6027\u7b49\u539f\u56e0\uff0c\u8fd9\u7c7b\u5b9e\u73b0\u4ecd\u7136\u5904\u5728\u63a2\u7d22\u9636\u6bb5\u3002\u53e6\u5916\uff0c\u6211\u4e2a\u4eba\u6bd4\u8f83\u62c5\u5fc3\uff08\u731c\u6d4b\uff09\u901a\u8fc7 ptrace \u76d1\u89c6\u7cfb\u7edf\u8c03\u7528\uff0c\u6027\u80fd\u662f\u5426\u4f1a\u53d7\u5230\u660e\u663e\u5f71\u54cd\u3002\u56e0\u6b64\u76ee\u524d\u6682\u65f6\u4e0d\u63a8\u8350\u3002\u5982\u679c\u4f60\u6709\u5174\u8da3\u7684\u8bdd\uff0c\u53ef\u4ee5\u770b\u770b graftcp \u9879\u76ee\u3002\n\u603b\u7ed3 \u4ee5\u4e0a\u662f\u6211\u77e5\u9053\u7684\u51e0\u4e4e\u6240\u6709\u5728 macOS \u4e0a\u914d\u7f6e\u4ee3\u7406\u7684\u65b9\u6cd5\u3002\u4e2a\u4eba\u6bd4\u8f83\u63a8\u8350\u524d\u51e0\u79cd\uff0c\u65e2\u80fd\u591f\u8986\u76d6\u5927\u591a\u6570\u573a\u666f\uff0c\u4e5f\u4e0d\u9700\u8981\u5b89\u88c5\u989d\u5916\u7684\u5e94\u7528\u3002\u5982\u679c\u4f60\u5bf9\u7f51\u7edc\u65b9\u9762\u611f\u5174\u8da3\uff0c\u4e5f\u4e0d\u59a8\u63a2\u7d22\u6027\u5730\u5c1d\u8bd5\u4e0b\u5176\u5b83\u65b9\u6848\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/redirecting-network-traffic-of-various-apps-on-macos-to-proxies\/","summary":"<p>\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u7ecf\u5e38\u9700\u8981\u4f7f\u7528\u5230\u56fd\u5916\u7684\u8d44\u6e90\uff0c\u4f8b\u5982\u5404\u79cd\u5305\u4f9d\u8d56\u7b49\u3002\u56fd\u5185\u76ee\u524d\u6bd4\u8f83\u666e\u904d\u7684\u505a\u6cd5\u662f\u4f7f\u7528\u7531\u77e5\u540d\u7b2c\u4e09\u65b9\u7ef4\u62a4\u7684\u56fd\u5185\u955c\u50cf\u3002\u867d\u7136\u65b9\u4fbf\uff0c\u4f46\u4e5f\u5b58\u5728\u4e00\u4e9b\u65e0\u6cd5\u907f\u514d\u7684\u95ee\u9898\uff0c\u4f8b\u5982\uff1a<\/p>\n<ul>\n<li>\u955c\u50cf\u53ef\u9760\u6027\u672a\u77e5\uff0c\u51fa\u95ee\u9898\u65f6\u6211\u4eec\u65e0\u80fd\u4e3a\u529b\uff0c\u53ea\u80fd\u7b49\u5f85\u7b2c\u4e09\u65b9\u4fee\u590d\u3002<\/li>\n<li>\u955c\u50cf\u540c\u6b65\u65f6\u95f4\u672a\u77e5\uff0c\u53ef\u80fd\u5b58\u5728\u6570\u636e\u6ede\u540e\u3002<\/li>\n<li>\u5b58\u5728\u5b89\u5168\u9690\u60a3\uff08\u5c3d\u7ba1\u53ef\u80fd\u6027\u8f83\u5c0f\uff09\u3002<\/li>\n<\/ul>\n<p>\u56e0\u6b64\uff0c\u6211\u4e2a\u4eba\u66f4\u52a0\u63a8\u8350\u4f9d\u8d56\u4ee3\u7406\u6765\u5b9e\u73b0\u5feb\u901f\u8bbf\u95ee\u6240\u9700\u8d44\u6e90\u7684\u76ee\u7684\u3002\u672c\u6587\u4e0d\u4f1a\u6d89\u53ca\u4efb\u4f55\u8fdd\u53cd\u6cd5\u5f8b\u6cd5\u89c4\u7684\u5185\u5bb9\uff0c\u53ea\u6765\u8c08\u8c08 macOS \u4e0b\u5982\u4f55\u8ba9\u4e0d\u540c\u5e94\u7528\u7684\u6d41\u91cf\u901a\u8fc7 <strong>\u672c\u5730\u7684<\/strong> \u4ee3\u7406\u670d\u52a1\u3002<\/p>","title":"\u76d8\u70b9\u4f7f macOS \u5e94\u7528\u6d41\u91cf\u901a\u8fc7\u4ee3\u7406\u7684\u591a\u79cd\u65b9\u5f0f"},{"content":"\u5728\u4e4b\u524d\u7684\u6587\u7ae0\u4e2d\uff0c\u6211\u4ecb\u7ecd\u4e86\uff1a\n \u5982\u4f55\u4f7f\u7528 GitLab CI \u5b9e\u73b0\u6301\u7eed\u90e8\u7f72\u3002 \u5982\u4f55\u4f7f\u7528 Helm \u548c Helmfile \u90e8\u7f72\u5e94\u7528\u5230 Kubernetes \u96c6\u7fa4\u4e2d\u3002  \u4f46\u8fd9\u5176\u4e2d\u7f3a\u5c11\u4e86\u5173\u952e\u7684\u4e00\u73af\uff1a\u521b\u5efa\u4e00\u4e2a\u5c5e\u4e8e\u4f60\u7684\u9879\u76ee\u7684 chart\uff0c\u8fd9\u6837\u624d\u80fd\u628a\u6211\u4eec\u5f00\u53d1\u7684\u9879\u76ee\u901a\u8fc7 Helm \u90e8\u7f72\u5230\u96c6\u7fa4\u4e2d\u3002\u672c\u6587\u5c06\u4f1a\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u6211\u4eec\u5982\u4f55\u521b\u5efa\u5e76\u7ef4\u62a4 chart\uff0c\u4ece\u800c\u6253\u901a\u4ece\u63d0\u4ea4\u4ee3\u7801\u5230\u90e8\u7f72\u7684\u5b8c\u6574\u6d41\u7a0b\u3002\nChart \u653e\u5728\u54ea \u5728\u521b\u5efa chart \u524d\uff0c\u9996\u5148\u8981\u8003\u8651\u7684\u95ee\u9898\u662f chart \u653e\u5728\u54ea\u3002\u76ee\u524d\u793e\u533a\u4e2d\u666e\u904d\u7684\u505a\u6cd5\u662f\u4e0e\u5e94\u7528\u4ee3\u7801\u5206\u5f00\u5b58\u653e\uff0c\u5c06 chart \u653e\u5728\u5355\u72ec\u7684\u4ed3\u5e93\u4e2d\uff0c\u5e76\u7531 CI \u8d1f\u8d23\u6253\u5305\u3001\u66f4\u65b0\u3002\u8fd9\u6837\u7684\u597d\u5904\u662f\uff1a\n Chart \u7684\u53d1\u7248\u5468\u671f\u4e0e\u5e94\u7528\u4e0d\u5fc5\u4fdd\u6301\u540c\u6b65\u3002 Commit tree \u66f4\u52a0\u6e05\u6670\u3002  \u56e0\u4e3a\u5f00\u6e90\u9879\u76ee\u7684 chart \u53ef\u80fd\u4f1a\u5728\u5176\u5b83\u5730\u65b9\u5b89\u88c5\uff0c\u6216\u662f\u6210\u4e3a\u67d0\u4e2a chart \u7684\u4f9d\u8d56\uff0c\u6240\u4ee5\u5fc5\u987b publish \u8fd9\u4e9b charts\u3002\u800c\u5bf9\u4e8e\u6211\u4eec\u8fd9\u7c7b\u95ed\u6e90\u5546\u4e1a\u9879\u76ee\uff0cchart \u4e0d\u4f1a\u88ab\u5916\u90e8\u9879\u76ee\u4f9d\u8d56\uff0c\u6211\u66f4\u63a8\u8350\u76f4\u63a5\u653e\u5728\u5e94\u7528\u4ee3\u7801\u4ed3\u5e93\u3002\u539f\u56e0\u5982\u4e0b\uff1a\n \u4e0d\u5fc5\u5355\u72ec\u914d\u7f6e CI \u6253\u5305\u3002 \u53d1\u7248\u8282\u594f\u4e0e\u5e94\u7528\u4fdd\u6301\u540c\u6b65\uff0c\u51fa\u95ee\u9898\u65f6\u65b9\u4fbf\u56de\u6eda\u3002  \u4f8b\u5982\u6211\u53f8\u51e0\u4e2a\u4e3b\u9879\u76ee\u7684 chart \u5168\u90e8\u5b58\u653e\u5728\u5404\u81ea\u4ee3\u7801\u4ed3\u5e93\u5185 deploy\/chart \u76ee\u5f55\u4e0b\uff1a\n\u521b\u5efa Chart \u548c Helmfile.yaml \u5728\u786e\u5b9a\u5b58\u653e\u4f4d\u7f6e\u540e\uff0c\u53ef\u4ee5\u5f00\u59cb\u521b\u5efa chart \u4e86\u3002\u5177\u4f53\u64cd\u4f5c\u4e0d\u96be\uff0c\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u5373\u53ef\uff1a\ncd deploy helm create api # api \u662f\u4f60\u5e0c\u671b\u521b\u5efa\u7684 chart \u540d\u79f0 \u4e0d\u8fc7\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cHelm \u9ed8\u8ba4\u4f1a\u5728\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a api\uff08\u53d6\u51b3\u4e8e\u4f60\u586b\u5199\u7684\u5177\u4f53\u540d\u79f0\uff09\u7684\u5b50\u76ee\u5f55\u7528\u4e8e\u5b58\u653e chart\u3002\u56e0\u6b64\u4f60\u9700\u8981\u624b\u52a8\u6267\u884c mv api chart\u3002\u4e0d\u8981\u5c1d\u8bd5\u76f4\u63a5\u8fd0\u884c helm create chart\uff0c\u56e0\u4e3a\u5728\u521b\u5efa\u65b0 chart \u7684\u8fc7\u7a0b\u4e2d\uff0c\u4f60\u586b\u5199\u7684\u540d\u79f0\u4f1a\u5728 chart templates \u5185\u88ab\u4f7f\u7528\uff0c\u66f4\u96be\u4ee5\u66ff\u6362\u3002\n\u53e6\u5916\uff0c\u6211\u4eec\u8fd8\u521b\u5efa\u4e86 helmfile.yaml\uff0c\u8fd9\u6837\u5728 CI \u4e2d\u6211\u4eec\u53ea\u9700\u8981\u8fd0\u884c helmfile -e $ENV apply \u5373\u53ef\u3002\nrepositories: - name: stable url: https:\/\/kubernetes-charts.storage.googleapis.com - name: bitnami url: https:\/\/charts.bitnami.com\/bitnami environments: stg: values: - .\/deploy\/values\/env.stg.yaml.gotmpl prd: values: - .\/deploy\/values\/env.prd.yaml.gotmpl helmDefaults: wait: true timeout: 180 releases: - name: {{ .Environment.Values.releaseName }} namespace: {{ .Environment.Values.namespace }} chart: .\/deploy\/chart # \u76f4\u63a5\u586b\u5199 Chart \u7684\u76f8\u5bf9\u8def\u5f84 secrets: - .\/deploy\/env\/secrets.{{ .Environment.Values.envName }}.yaml values: - .\/deploy\/values\/values.{{ .Environment.Name }}.yaml.gotmpl \u5173\u4e8e Helmfile \u7684\u57fa\u7840\u4f7f\u7528\uff0c\u53ef\u53c2\u8003\u6211\u4e4b\u524d\u7684\u535a\u6587 \u2014 K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u4e86\u89e3 Helmfile\u3002\n\u503c\u5f97\u4e00\u63d0\u7684\u662f\uff0c\u6211\u4eec\u914d\u7f6e\u4e86\u4e24\u4e2a Helm \u9ed8\u8ba4\u53c2\u6570\u3002\n\u5176\u4e2d\uff0cwait \u914d\u7f6e\u4e3a true\uff0c\u8fd9\u6837\u5728 CI \u73af\u5883\u4e2d\u8fd0\u884c\u65f6\uff0c\u76f4\u5230\u90e8\u7f72\u7684\u8d44\u6e90\u72b6\u6001\u53d8\u4e3a Ready \u540e\uff0cPipeline \u624d\u4f1a\u53d8\u4e3a\u6210\u529f\u72b6\u6001\u3002\u5982\u679c\u4e0d\u542f\u7528\u8be5\u53c2\u6570\uff0c\u90a3\u4e48\u53ea\u8981\u8d44\u6e90\u6b63\u5e38\u521b\u5efa\uff0cHelm \u5c31\u4f1a\u5b8c\u6210\u3001\u9000\u51fa\uff0c\u8fd9\u65f6 Pod \u6216\u8bb8\u5e76\u6ca1\u6709\u542f\u52a8\uff0c\u53ef\u80fd\u51fa\u73b0\u65e0\u6cd5\u8c03\u5ea6\u3001\u62c9\u53d6\u955c\u50cf\u5931\u8d25\u7b49\uff0c\u8fd9\u4e9b\u95ee\u9898\u5e94\u5f53\u5c5e\u4e8e\u90e8\u7f72\u5931\u8d25\u7684\u8303\u7574\u3002\u56e0\u6b64\uff0c\u4e3a\u4e86\u8ba9 CI \u6267\u884c\u7ed3\u679c\u66f4\u52a0\u51c6\u786e\uff0c\u6211\u4eec\u5f00\u542f\u4e86\u8be5\u53c2\u6570\u3002\n\u53e6\u5916\uff0c\u4e3a\u4e86\u9632\u6b62 Pipeline \u65f6\u95f4\u8fc7\u957f\uff0ctimeout \u8bbe\u7f6e\u4e3a 180 \u79d2\u3002\n\u65b0\u589e\u6216\u8c03\u6574\u8d44\u6e90\u6a21\u677f \u65b0\u521b\u5efa\u7684 chart \u5305\u542b\u4e00\u4e9b\u5e38\u7528\u8d44\u6e90\u7684\u6a21\u677f\uff0c\u4f8b\u5982 Ingress\u3001Deployment \u7b49\u3002\u4f60\u53ef\u4ee5\u6839\u636e\u9700\u8981\u6dfb\u52a0\u5176\u5b83\u8d44\u6e90\uff0c\u6a21\u677f\u8bed\u6cd5\u53ef\u53c2\u8003 Go template \u5b98\u65b9\u6587\u6863\u5373\u53ef\u3002\n\u5982\u679c\u4e0d\u77e5\u4ece\u4f55\u4e0b\u624b\u521b\u5efa\u65b0\u8d44\u6e90\uff0c\u6211\u63a8\u8350\u770b\u770b\u8fd9\u4e2a\u9879\u76ee\uff1ahttps:\/\/github.com\/dennyzhang\/kubernetes-yaml-templates\uff0c\u8fd9\u5176\u4e2d\u5305\u542b\u4e86\u4e0d\u5c11\u5e38\u7528\u7684 Kubernetes \u8d44\u6e90\u4f8b\u5b50\uff0c\u4f60\u53ef\u4ee5\u76f4\u63a5\u590d\u5236\u5e76\u6539\u9020\u6210 Go template\u3002\u901a\u5e38\u9700\u8981\u4fee\u6539\u7684\u6709\u4e24\u70b9\uff0c\u4ee5 ConfigMap \u4e3a\u4f8b\uff1a\napiVersion: v1 kind: ConfigMap metadata: name: {{ include &#34;api.fullname&#34; . }} labels: {{- include &#34;api.labels&#34; . | nindent 4 }} # ... \u9996\u5148\u5c06\u8d44\u6e90\u540d\u79f0\u4fee\u6539\u4e3a\u4e0e\u5176\u5b83\u8d44\u6e90\u4e00\u81f4\uff0c\u4f7f\u7528\u6a21\u677f\u6e32\u67d3\u7684 fullname\u3002\u5176\u6b21\u4fee\u6539 labels \u5b57\u6bb5\uff0c\u4e00\u822c\u6765\u8bf4\u4f7f\u7528 Helm \u81ea\u5e26\u8f85\u52a9\u51fd\u6570\u6e32\u67d3\u7684 labels \u5373\u53ef\u3002\n\u6ce8\u610f\uff0capi.fullname \u548c api.labels \u4e0d\u662f\u56fa\u5b9a\u7684\uff0capi \u662f\u4f60\u7684 chart \u540d\u79f0\u3002\n\u7f16\u8f91 Values \u5728\u65b0\u589e\u5176\u5b83\u8d44\u6e90\u540e\uff0c\u4f60\u53ef\u4ee5\u5f15\u7528\u66f4\u591a\u81ea\u5b9a\u4e49\u7684 values\uff0c\u4f8b\u5982\uff1a\napiVersion: v1 kind: ConfigMap # ... data: APP_ENV: {{ .Values.app.env }} \u6211\u4eec\u5c06 APP_ENV \u914d\u7f6e\u4e3a values \u4e2d app.env \u7684\u503c\u3002\u5728\u5f15\u7528\u65b0\u7684 values \u540e\uff0c\u6211\u63a8\u8350\u4e00\u5e76\u4fee\u6539 chart \u5185 values.yaml \u7684\u5185\u5bb9\uff0c\u4fdd\u6301\u6a21\u677f\u4e0e values \u7684\u540c\u6b65\uff0c\u8fd9\u6837\u5728\u589e\u52a0\u65b0\u73af\u5883\u65f6\u5c31\u6709\u4e00\u4efd\u300c\u57fa\u7840\u300dvalues \u7528\u4e8e\u53c2\u8003\u53ef\u4f9b\u4fee\u6539\u7684\u914d\u7f6e\u3002\u4f8b\u5982\uff1a\n# ... app: env: production # ... \u4f9d\u8d56\u5176\u5b83 Chart \u901a\u5e38\u6211\u4eec\u7684\u5e94\u7528\u4f1a\u4f9d\u8d56\u4e00\u4e9b\u77e5\u540d\u7684\u5f00\u6e90\u7ec4\u4ef6\uff0c\u4f8b\u5982 Redis\u3001MySQL \u7b49\u3002Helm \u5141\u8bb8\u6211\u4eec\u5c06\u5176\u5b83 chart \u58f0\u660e\u4e3a\u4f9d\u8d56\uff0c\u5728 chart \u7684\u5b89\u88c5\u8fc7\u7a0b\u4e2d\uff0c\u4e5f\u4f1a\u540c\u65f6\u5b89\u88c5\u4f9d\u8d56\u7684 charts\uff0c\u4ece\u800c\u8fbe\u6210\u540c\u65f6\u5b89\u88c5\u5e94\u7528\u4ee5\u53ca\u76f8\u5173\u6240\u9700\u670d\u52a1\u7684\u76ee\u7684\u3002\n\u65b0\u7248 Helm v3 \u4e2d\u63d0\u4f9b\u4e86\u5bf9 Chart v2 \u7684\u652f\u6301\uff0c\u539f\u5148 Chart v1 \u4e2d\u7684 dependencies.yaml \u88ab\u5e9f\u5f03\u4e86\u3002\u7f16\u8f91 Chart.yaml\uff0c\u6dfb\u52a0 dependencies \u90e8\u5206\u5373\u53ef\uff1a\napiVersion: v2 # ... dependencies: - name: redis  # Chart \u540d\u79f0 version: 10.5.10 # Chart \u7248\u672c repository: https:\/\/charts.bitnami.com\/bitnami # Chart Repo \u6267\u884c helm dep build \u5373\u53ef\u62c9\u53d6\u4f9d\u8d56\u5e76\u751f\u6210 Chart.lock\u3002\u6700\u540e\uff0c\u7531\u4e8e\u4f9d\u8d56\u7684 chart \u7684\u53d1\u884c\u5305\u5b58\u50a8\u5728 chart \u4e0b\u7684 charts \u5b50\u76ee\u5f55\u4e2d\uff0c\u56e0\u6b64\u5efa\u8bae\u5c06 deploy\/chart\/charts \u8def\u5f84\u6dfb\u52a0\u5230 .gitignore \u6587\u4ef6\u5185\uff0c\u4ee5\u9632\u6b62\u5c06\u4f9d\u8d56\u4ee3\u7801\u63d0\u4ea4\u5230 Git \u7248\u672c\u7ba1\u7406\u4e2d\u3002\n\u5c0f\u7ed3 \u521b\u5efa\u5e76\u7ef4\u62a4\u4e00\u4e2a\u53ef\u9760\u7684 chart \u5e76\u4e0d\u5bb9\u6613\uff0c\u5728\u4e0d\u65ad\u5b8c\u5584\u7684\u8fc7\u7a0b\u4e2d\u6211\u4eec\u6295\u5165\u4e86\u5927\u91cf\u7cbe\u529b\u6539\u8fdb\u548c\u4f18\u5316\u3002\u6709\u5174\u8da3\u7684\u540c\u5b66\u63a8\u8350\u8bfb\u4e00\u4e0b Helm \u5b98\u65b9\u548c Bitnami \u63d0\u4f9b\u7684 Helm chart \u6700\u4f73\u5b9e\u8df5\u6587\u6863\uff0c\u76f8\u4fe1\u4f1a\u5bf9\u4f60\u6709\u6240\u5e2e\u52a9\uff1a\n https:\/\/helm.sh\/docs\/chart_best_practices\/ https:\/\/docs.bitnami.com\/tutorials\/series\/best-practices-helm\/ ","permalink":"https:\/\/wi1dcard.dev\/posts\/create-and-maintain-a-helm-chart\/","summary":"<p>\u5728\u4e4b\u524d\u7684\u6587\u7ae0\u4e2d\uff0c\u6211\u4ecb\u7ecd\u4e86\uff1a<\/p>\n<ul>\n<li>\u5982\u4f55\u4f7f\u7528 GitLab CI \u5b9e\u73b0\u6301\u7eed\u90e8\u7f72\u3002<\/li>\n<li>\u5982\u4f55\u4f7f\u7528 Helm \u548c Helmfile \u90e8\u7f72\u5e94\u7528\u5230 Kubernetes \u96c6\u7fa4\u4e2d\u3002<\/li>\n<\/ul>\n<p>\u4f46\u8fd9\u5176\u4e2d\u7f3a\u5c11\u4e86\u5173\u952e\u7684\u4e00\u73af\uff1a\u521b\u5efa\u4e00\u4e2a\u5c5e\u4e8e\u4f60\u7684\u9879\u76ee\u7684 chart\uff0c\u8fd9\u6837\u624d\u80fd\u628a\u6211\u4eec\u5f00\u53d1\u7684\u9879\u76ee\u901a\u8fc7 Helm \u90e8\u7f72\u5230\u96c6\u7fa4\u4e2d\u3002\u672c\u6587\u5c06\u4f1a\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u6211\u4eec\u5982\u4f55\u521b\u5efa\u5e76\u7ef4\u62a4 chart\uff0c\u4ece\u800c\u6253\u901a\u4ece\u63d0\u4ea4\u4ee3\u7801\u5230\u90e8\u7f72\u7684\u5b8c\u6574\u6d41\u7a0b\u3002<\/p>","title":"K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u79c1\u6709 Helm Chart \u7684\u521b\u5efa\u4e0e\u7ef4\u62a4"},{"content":"\u5728 Kubernetes \u4e2d\u5b9e\u73b0 TLS termination \u975e\u5e38\u5bb9\u6613\u3002Ingress \u8d44\u6e90\u5305\u542b\u4e00 secretName \u5c5e\u6027\uff0c\u7528\u4e8e\u6307\u5b9a Secret \u8d44\u6e90\u540d\u79f0\u3002\u5728\u53d6\u5f97\u8bc1\u4e66\u540e\uff0c\u901a\u8fc7 kubectl create secret tls tls-secret --key tls.key --cert tls.crt \u521b\u5efa Secret \u5b58\u50a8\u8bc1\u4e66\uff0c\u4fbf\u53ef\u4ee5\u88ab Ingress \u4f7f\u7528\u4e86\u3002\n\u552f\u72ec\u6709\u4e9b\u4e0d\u65b9\u4fbf\u7684\u662f\uff0c\u8bc1\u4e66\u7684\u7533\u8bf7\u4ee5\u53ca\u521b\u5efa Secret \u7684\u8fc7\u7a0b\u9700\u8981\u624b\u52a8\u6267\u884c\u3002\u5728\u8bc1\u4e66\u5373\u5c06\u8fc7\u671f\u524d\uff0c\u8fd8\u9700\u8981\u4eba\u5de5\u7eed\u671f\u3002\u5728\u4f20\u7edf VM \u90e8\u7f72\u7684\u573a\u666f\u4e0b\uff0c\u53ef\u4ee5\u4f7f\u7528\u4f8b\u5982 certbot \u6216 acme.sh \u7b49\u9879\u76ee\uff0c\u914d\u5408 Let&amp;rsquo;s Encrypt \u81ea\u52a8\u7533\u8bf7\u5e76\u5b9a\u671f\u7eed\u7b7e\u8bc1\u4e66\u3002\u800c\u5728 K8s \u96c6\u7fa4\u4e2d\u5982\u4f55\u964d\u4f4e\u8bc1\u4e66\u7ef4\u62a4\u6210\u672c\uff1f\u6765\u770b\u770b\u6211\u4eec\u662f\u600e\u4e48\u505a\u7684\u3002\n\u8ba4\u8bc6 Cert-Manager Cert-manager \u987e\u540d\u601d\u4e49\uff0c\u662f\u4e00\u6b3e\u7ba1\u7406\u8bc1\u4e66\u7684\u5de5\u5177\u3002\u6839\u636e\u5b98\u7f51\u7684\u63cf\u8ff0\uff1a\n cert-manager builds on top of Kubernetes, introducing certificate authorities and certificates as first-class resource types in the Kubernetes API. This makes it possible to provide &lsquo;certificates as a service&rsquo; to developers working within your Kubernetes cluster.\n \u7b80\u5355\u6765\u8bf4\uff0ccert-manager \u5229\u7528 Kubernetes \u7684 CRD \u7279\u6027\u63d0\u4f9b\u4e86\u540d\u4e3a Certificate \u7b49\u8d44\u6e90\uff0c\u5b9e\u73b0\u300c\u8bc1\u4e66\u5373\u670d\u52a1\u300d\u3002\u8bf7\u770b\u63a5\u4e0b\u6765\u7684\u4f8b\u5b50\u3002\n\u5b89\u88c5 Cert-Manager Cert-manager \u7684\u5b89\u88c5\u65b9\u6cd5\u6709\u591a\u79cd\uff0c\u53ef\u901a\u8fc7 kubectl \u76f4\u63a5 apply \u6240\u6709 manifest\uff1b\u4e5f\u53ef\u4ee5\u5148\u5b89\u88c5 CRD\uff0c\u518d\u901a\u8fc7 Helm \u5b89\u88c5\u5176\u5b83\u8d44\u6e90\u3002\n\u6211\u4e2a\u4eba\u503e\u5411\u4e8e\u540e\u8005\u3002\u4e00\u952e apply \u56fa\u7136\u7b80\u5355\uff0c\u4f46\u6ca1\u6709\u673a\u4f1a\u8c03\u6574\u4efb\u4f55\u914d\u7f6e\u3002\u4f7f\u7528 Helm \u5b89\u88c5 cert-manager \u7684 Chart \u5219\u53ef\u4ee5\u6839\u636e\u9700\u8981\u8c03\u6574\u90e8\u5206\u9009\u9879\u3002\u5177\u4f53\u8fc7\u7a0b\u9650\u4e8e\u7bc7\u5e45\u4e0d\u518d\u8be6\u8ff0\uff0c\u8bf7\u67e5\u9605\u5b98\u65b9\u6587\u6863\uff0c\u4ec5\u5c55\u793a\u6211\u4eec\u4f7f\u7528\u7684 helmfile.yaml \u4ee5\u4f9b\u53c2\u8003\uff1a\nrepositories: - name: jetstack url: https:\/\/charts.jetstack.io releases: - name: cert-manager namespace: cert-manager chart: jetstack\/cert-manager version: ^0.14.0 values: - values\/cert-manager\/values.yaml \u914d\u7f6e Cert-Manager \u521b\u5efa Issuer Issuer \u7684\u4f5c\u7528\u4e3b\u8981\u662f\u6307\u5b9a\u8bc1\u4e66\u4ee5\u4f55\u79cd\u65b9\u5f0f\u7b7e\u53d1\u3002\u76ee\u524d cert-manager \u652f\u6301\u7684 Issuer \u7c7b\u578b\u6709 ACME\u3001SelfSigned \u7b49\u3002\u5176\u4e2d\uff0cACME \u652f\u6301\u7684\u9a8c\u8bc1\u7c7b\u578b\u5305\u62ec HTTP01 \u548c DNS01\u3002\n\u4f7f\u7528 HTTP01 \u9a8c\u8bc1 cert-manager \u5c06\u4f1a\u4fee\u6539\u6216\u521b\u5efa\u65b0\u7684 Ingress \u8d44\u6e90\u7528\u6765\u5904\u7406 ACME \u670d\u52a1\u7684\u9a8c\u8bc1\u8bf7\u6c42\u3002\u800c DNS01 \u5219\u53ea\u9700\u914d\u7f6e DNS \u670d\u52a1\u63d0\u4f9b\u5546\u7684\u5bc6\u94a5\uff0ccert-manager \u8d1f\u8d23\u7ef4\u62a4\u5bf9\u5e94\u7684\u9a8c\u8bc1\u8bb0\u5f55\u5373\u53ef\u3002\u6211\u4eec\u4f7f\u7528\u7684\u662f AWS \u7684 Route53 \u670d\u52a1\uff0c\u6b63\u597d\u4e5f\u5728 cert-manager \u5185\u7f6e\u652f\u6301\u7684 DNS provider \u5217\u8868 \u5185\u3002\u56e0\u6b64\u6211\u4eec\u9009\u7528\u4e86\u540e\u8005\u3002\n\u53e6\u5916\uff0ccert-manager \u63d0\u4f9b\u4e86\u4e24\u79cd Issuer \u2014 Issuer \u548c ClusterIssuer\uff0c\u524d\u8005\u4ec5\u9650\u4e8e Issuer \u6240\u5728\u7684\u547d\u540d\u7a7a\u95f4\u5185\u4f7f\u7528\uff0c\u800c ClusterIssuer \u53ef\u5728\u96c6\u7fa4\u5185\u7684\u4efb\u610f\u547d\u540d\u7a7a\u95f4\u901a\u7528\u3002\n\u6211\u4eec\u521b\u5efa\u4e86\u4e24\u4e2a ClusterIssuer\uff0c\u540d\u53eb letsencrypt-prd \u548c letsencrypt-stg\uff0c\u4f8b\u5982\uff1a\napiVersion: cert-manager.io\/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt-prd spec: acme: email: user@example.com server: https:\/\/acme-v02.api.letsencrypt.org\/directory privateKeySecretRef: name: letsencrypt-prd # \u7528\u4e8e\u50a8\u5b58 ACME Account \u79c1\u94a5\u7684 Secret solvers: - selector: {} dns01: route53: # Route53 \u76f8\u5173\u53c2\u6570 region: us-east-2 accessKeyID: ... # AWS Access Key ID secretAccessKeySecretRef: name: route53-secret-access-key # \u5b58\u50a8 AWS Access Key Secret \u7684 Kubernetes Secret \u540d\u79f0 key: secret_access_key # \u5b58\u50a8 AWS Access Key Secret \u503c\u7684\u5b57\u6bb5\u540d \u4fee\u6539 Chart Values \u5728\u4e0a\u9762\u7684 helmfile.yaml \u4e2d\uff0c\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u914d\u7f6e\u4e86 values \u6587\u4ef6 values\/cert-manager\/values.yaml\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a\ningressShim: defaultIssuerKind: ClusterIssuer defaultIssuerName: letsencrypt-prd # \u521a\u521a\u521b\u5efa\u7684 ClusterIssuer \u540d\u79f0 \u6211\u4eec\u914d\u7f6e\u4e86\u9488\u5bf9 ingressShim \u7684\u9ed8\u8ba4 Issuer\u3002\u8fd9\u6837\u6211\u4eec\u5c31\u53ef\u4ee5\u4e0d\u624b\u52a8\u521b\u5efa Certificate\uff0ccert-manager \u5c06\u4f1a\u300c\u76d1\u89c6\u300d\u96c6\u7fa4\u5185\u7684 Ingress \u8d44\u6e90\uff0c\u5f53\u6709 Ingress \u914d\u7f6e\u4e86 spec.tls \u65f6\uff0c\u81ea\u52a8\u8bfb\u53d6 hosts\u3001\u521b\u5efa\u8bc1\u4e66\u5e76\u5c06\u8bc1\u4e66\u5b58\u50a8\u81f3 secretName \u6307\u5b9a\u7684 Secret \u5185\uff0c\u5b9e\u73b0\u5b8c\u5168\u81ea\u52a8\u5316\u3002\n\u521b\u5efa\u5e76\u4f7f\u7528\u8bc1\u4e66 \u7531\u4e8e\u5f00\u542f\u4e86 ingressShim \u529f\u80fd\uff0c\u56e0\u6b64\u6211\u4eec\u53ea\u8981\u6309\u7167\u901a\u5e38\u601d\u8def\u4f7f\u7528 Ingress \u5373\u53ef\u3002\u4f8b\u5982\uff1a\napiVersion: extensions\/v1beta1 kind: Ingress metadata: name: api namespace: staging spec: rules: - host: example.com http: paths: - backend: serviceName: api servicePort: http path: \/ tls: - secretName: api-tls-certificate \u628a spec.tls.secretName \u8bbe\u7f6e\u4e3a\u60f3\u8981\u5b58\u50a8\u8bc1\u4e66\u7684 Secret \u540d\u79f0\uff08\u4f8b\u5982\u4f8b\u5b50\u4e2d\u7684 api-tls-certificate\uff09\uff0ccert-manager \u5c06\u8bfb\u53d6\u8fd9\u4e2a\u540d\u79f0\u5e76\u5c06\u7533\u8bf7\u597d\u7684\u8bc1\u4e66\u5b58\u50a8\u5230\u8be5 Secert \u5185\uff0c\u4ee5\u4f9b Ingress \u4f7f\u7528\u3002\n\u5c0f\u7ed3 \u6839\u636e\u4e0a\u6587\u7684\u4ecb\u7ecd\uff0c\u4f3c\u4e4e\u8fd9\u662f\u4e00\u5957\u5b8c\u7f8e\u7684\u89e3\u51b3\u65b9\u6848\uff1f\u4e0d\u5c3d\u7136\u3002\n\u76ee\u524d cert-manager \u9879\u76ee\u8fd8\u5904\u4e8e beta \u9636\u6bb5\uff0c\u6bcf\u6b21\u53d1\u5e03\u65b0\u7684 release \u90fd\u53ef\u80fd\u5305\u542b breaking change\u3002\u5728\u6211\u4eec\u4f7f\u7528\u7684\u8fd9\u6bb5\u65f6\u95f4\u5185\uff0c\u6bcf\u9694\u51e0\u4e2a\u7248\u672c\u5c31\u9700\u8981\u624b\u52a8\u5347\u7ea7\u4e00\u6b21\uff0c\u5347\u7ea7\u8fc7\u7a0b\u4e2d\u6709\u65f6\u4f1a\u51fa\u73b0\u4e00\u4e9b\u610f\u6599\u4e4b\u5916\u7684\u5c0f\u95ee\u9898\u3002\u4f8b\u5982\u6700\u8fd1\u7684 0.13 -&gt; 0.14 \u5347\u7ea7\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u65b0\u7248\u672c\u7684 CRD manifests \u786c\u7f16\u7801\u8981\u6c42\u76f8\u5173\u8d44\u6e90\u5fc5\u987b\u5b89\u88c5\u5230 cert-manager \u547d\u540d\u7a7a\u95f4\u3002\u5e0c\u671b cert-manager \u5b98\u65b9\u80fd\u5c3d\u5feb\u63a8\u8fdb\u6b63\u5f0f\u7248\u7684\u53d1\u5e03\uff0c\u51cf\u5c11\u624b\u52a8\u5347\u7ea7\u7684\u6b21\u6570\u548c\u6210\u672c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/getting-to-know-cert-manager\/","summary":"<p>\u5728 Kubernetes \u4e2d\u5b9e\u73b0 TLS termination \u975e\u5e38\u5bb9\u6613\u3002Ingress \u8d44\u6e90\u5305\u542b\u4e00 <code>secretName<\/code> \u5c5e\u6027\uff0c\u7528\u4e8e\u6307\u5b9a Secret \u8d44\u6e90\u540d\u79f0\u3002\u5728\u53d6\u5f97\u8bc1\u4e66\u540e\uff0c\u901a\u8fc7 <code>kubectl create secret tls tls-secret --key tls.key --cert tls.crt<\/code> \u521b\u5efa Secret \u5b58\u50a8\u8bc1\u4e66\uff0c\u4fbf\u53ef\u4ee5\u88ab Ingress \u4f7f\u7528\u4e86\u3002<\/p>\n<p>\u552f\u72ec\u6709\u4e9b\u4e0d\u65b9\u4fbf\u7684\u662f\uff0c\u8bc1\u4e66\u7684\u7533\u8bf7\u4ee5\u53ca\u521b\u5efa Secret \u7684\u8fc7\u7a0b\u9700\u8981\u624b\u52a8\u6267\u884c\u3002\u5728\u8bc1\u4e66\u5373\u5c06\u8fc7\u671f\u524d\uff0c\u8fd8\u9700\u8981\u4eba\u5de5\u7eed\u671f\u3002\u5728\u4f20\u7edf VM \u90e8\u7f72\u7684\u573a\u666f\u4e0b\uff0c\u53ef\u4ee5\u4f7f\u7528\u4f8b\u5982 <a href=\"https:\/\/certbot.eff.org\/\" target=\"_blank\">certbot<\/a> \u6216 <a href=\"https:\/\/github.com\/acmesh-official\/acme.sh\" target=\"_blank\">acme.sh<\/a> \u7b49\u9879\u76ee\uff0c\u914d\u5408 <a href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\">Let&amp;rsquo;s Encrypt<\/a> \u81ea\u52a8\u7533\u8bf7\u5e76\u5b9a\u671f\u7eed\u7b7e\u8bc1\u4e66\u3002\u800c\u5728 K8s \u96c6\u7fa4\u4e2d\u5982\u4f55\u964d\u4f4e\u8bc1\u4e66\u7ef4\u62a4\u6210\u672c\uff1f\u6765\u770b\u770b\u6211\u4eec\u662f\u600e\u4e48\u505a\u7684\u3002<\/p>","title":"K8s \u4e0b\u7684 TLS \u8bc1\u4e66\u7ba1\u7406 \u2014 \u4e86\u89e3 Cert-Manager"},{"content":"\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u4e86 Helm \u7684\u521d\u6b65\u4f7f\u7528\u3002\u7136\u800c\u8fd9\u4ecd\u7136\u4e0d\u80fd\u6ee1\u8db3\u6211\u53f8\u7684\u5de5\u4f5c\u6d41\uff0c\u4e3b\u8981\u95ee\u9898\u6709\uff1a\n Helm \u4e0d\u63d0\u4f9b apply \u547d\u4ee4\uff1b\u56e0\u6b64\u5728 CI\/CD \u573a\u666f\u4e2d\u5fc5\u987b\u8003\u8651\u5230\u5224\u65ad\u662f install \u8fd8\u662f upgrade\u3002 \u4e0d\u65b9\u4fbf\u63a7\u5236\u5b89\u88c5\u7684 chart \u7248\u672c\uff1b\u4f8b\u5982\u6307\u5b9a\u7248\u672c\u8303\u56f4\u3001\u9501\u5b9a\u67d0\u4e00\u7248\u672c\u7b49\u3002 Values \u5fc5\u987b\u662f\u7eaf\u6587\u672c\uff1b\u4e0d\u652f\u6301\u6a21\u677f\u6e32\u67d3\u3001\u4e0d\u65b9\u4fbf\u533a\u5206\u73af\u5883\u3002  \u56e0\u6b64\u6211\u4eec\u9700\u8981 Helm Releases as Code\u3002\u6211\u542c\u8bf4\u8fc7\u7684\u4ea7\u54c1\u6709 Helmsman \u548c Helmfile \u4e24\u6b3e\u3002\u76ee\u524d\u6211\u4eec\u56e2\u961f\u5df2\u7ecf\u4f7f\u7528\u540e\u8005\u4e00\u6bb5\u65f6\u95f4\uff0c\u5e76\u4e14\u6709\u56e2\u961f\u6210\u5458\u8d21\u732e\u8fc7\u90e8\u5206\u4ee3\u7801\u3002\n\u81f3\u4e8e\u4e3a\u4ec0\u4e48\u9009\u62e9 Helmfile\uff0c\u80cc\u540e\u7684\u771f\u6b63\u539f\u56e0\u662f\u5728\u53d1\u73b0 Helmfile \u7684\u65f6\u5019\u8fd8\u6ca1\u542c\u8bf4\u8fc7 Helmsman\u3002\u540e\u6765\u4e86\u89e3 Helmsman \u5e76\u5c1d\u8bd5\u540e\u53d1\u73b0\u5b83\u5e76\u6ca1\u6709\u89e3\u51b3\u6211\u4eec\u540e\u4e24\u4e2a\u95ee\u9898\uff0c\u56e0\u6b64\u4e5f\u5c31\u6ca1\u6709\u66ff\u6362\u4e86\u3002\n\u63a5\u4e0b\u6765\u6211\u9488\u5bf9\u4ee5\u4e0a\u51e0\u4e2a\u75db\u70b9\u6765\u8bf4\u8bf4\u6211\u4eec\u662f\u600e\u4e48\u505a\u7684\u3002\n\u4e00\u952e Apply Helmfile \u7684\u6587\u6863\u975e\u5e38\u7b80\u660e\u3001\u76f4\u63a5\uff0c\u793a\u4f8b\u914d\u7f6e\u6587\u4ef6 \u5c31\u5728 README \u91cc\u3002\u6211\u8282\u9009\u4e00\u5c0f\u6bb5\u6765\u8bf4\u51e0\u4e2a\u5fc5\u8981\u7684\u914d\u7f6e\u9879\uff1a\nrepositories: - name: bitnami url: https:\/\/charts.bitnami.com\/bitnami releases: - name: my-release  # Release name namespace: staging  # Release namespace chart: bitnami\/redis # Chart name values: # \u7b49\u6548\u4e8e helm \u7684 --values \u9009\u9879 - foo.yaml set: # \u7b49\u6548\u4e8e helm \u7684 --set \u9009\u9879 - name: cluster.enabled value: &#34;false&#34; \u5c06\u4ee5\u4e0a\u5185\u5bb9\u4fdd\u5b58\u4e3a helmfile.yaml \u6587\u4ef6\uff0c\u968f\u540e\u6267\u884c helmfile apply \u5373\u53ef\u3002Helmfile \u5c06\u4f1a\u5e2e\u6211\u4eec\uff1a\n \u6dfb\u52a0 repositories \u4e2d\u58f0\u660e\u7684 Helm chart repo\u3002 \u6839\u636e release \u5c0f\u8282\u5185\u7684\u914d\u7f6e\uff0c\u5b89\u88c5\u6216\u66f4\u65b0 chart\u3002  \u56e0\u6b64\uff0c\u4e0a\u7bc7\u6587\u7ae0\u4e2d\u63d0\u5230\u7684\uff1a\nhelm repo add ... helm install ... helm upgrade ... \u53ef\u76f4\u63a5\u88ab\u7b80\u5316\u4e3a\uff1a\nhelmfile apply \u540c\u65f6\uff0c\u5982\u679c\u4f60\u5b89\u88c5\u4e86 helm-diff \u63d2\u4ef6\uff0cHelmfile \u8fd8\u4f1a\u5728\u6267\u884c\u64cd\u4f5c\u524d\u8f93\u51fa\u6e05\u6670\u7684 diff\uff1a\n\u5177\u4f53\u5b89\u88c5\u8fc7\u7a0b\u672c\u6587\u4e0d\u518d\u8be6\u8ff0\u3002\nChart \u7248\u672c\u63a7\u5236 \u5927\u591a\u6570\u793e\u533a\u63d0\u4f9b\u7684 charts \u90fd\u91c7\u7528 Semver 2.0 \u4f5c\u4e3a\u7248\u672c\u53f7\u3002\u56e0\u6b64\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u6211\u4eec\u90fd\u5e0c\u671b\u9501\u5b9a\u4e3b\u7248\u672c\uff0c\u9632\u6b62\u8bef\u5347\u7ea7\u5f15\u5165 breaking change\u3002Helmfile \u63d0\u4f9b\u4e86 version \u53c2\u6570\u53ef\u7528\u4e8e\u6307\u5b9a\u7248\u672c\u8303\u56f4\uff0c\u4f8b\u5982\uff1a\n# ... releases: - name: my-release namespace: staging chart: bitnami\/redis version: ^10.5.13 # \u9632\u6b62\u5347\u7ea7\u5230 v11.x.x # ... \u540c\u65f6\uff0cHelmfile \u8fd8\u63d0\u4f9b\u4e86 lock \u6587\u4ef6\uff0c\u529f\u80fd\u4e0e\u5e38\u89c1\u7248\u672c\u7ba1\u7406\u5668\u4e2d\u7684 lock \u7c7b\u4f3c\u3002\u914d\u5408 CI \u65f6\uff0c\u9664\u975e\u63d0\u4ea4\u4ee3\u7801\u6539\u52a8 lock \u6587\u4ef6\uff0c\u5426\u5219\u5728\u4efb\u610f\u65f6\u95f4\u70b9\u6267\u884c CI \u5b89\u88c5\u7684 chart \u7248\u672c\u662f\u4e00\u81f4\u7684\u3002\n\u4f60\u53ef\u4ee5\u901a\u8fc7 helmfile deps \u547d\u4ee4\u751f\u6210 lock\uff0c\u4ee5\u4e0a helmfile.yaml \u751f\u6210\u7684\u793a\u4f8b helmfile.lock \u6587\u4ef6\u957f\u8fd9\u6837\uff1a\nversion: v0.102.0 dependencies: - name: redis repository: https:\/\/charts.bitnami.com\/bitnami version: 10.5.13 digest: sha256:20f2840c2642bf98f03d2b5cf890c73e1f2c100a0f0475777ae7788b2a0ae98d generated: &#34;2020-03-24T14:14:01.663801+08:00&#34; \u53ef\u770b\u51fa\u5305\u542b\u5177\u4f53\u7684 chart \u7248\u672c\u3001Helmfile \u7248\u672c\u3001\u54c8\u5e0c\u503c\u3001\u751f\u6210\u65f6\u95f4\u7b49\u53c2\u6570\u3002\n\u5f53\u9700\u8981\u66f4\u65b0 lock \u6587\u4ef6\u65f6\uff0c\u540c\u6837\u6267\u884c helmfile deps \u5373\u53ef\u3002\n\u52a8\u6001 Values \u5728 CI \u4e0a\u90e8\u7f72\u65f6\uff0c\u6709\u4e9b values \u7684\u503c\u4e0d\u662f\u56fa\u5b9a\u7684\uff0c\u53ef\u80fd\u6765\u81ea\u4e8e\u73af\u5883\u53d8\u91cf\uff0c\u4e5f\u53ef\u80fd\u7531\u4e8e\u73af\u5883\u5dee\u5f02\u800c\u4e0d\u540c\u3002\n\u73af\u5883\u53d8\u91cf \u5728\u4e4b\u524d\u7684\u6587\u7ae0\u4e2d\u6211\u4eec\u4ecb\u7ecd\u8fc7 review apps\uff0c\u5176\u4e2d\u6709\u4e00\u9879\u5f88\u91cd\u8981\u7684\u9700\u6c42\u662f\uff0c\u6bcf\u6b21\u5f00\u65b0\u5206\u652f\u90e8\u7f72\u7684 release \u4e0d\u80fd\u540c\u540d\uff0c\u5426\u5219\u8d44\u6e90\u4f1a\u56e0\u4e3a\u91cd\u540d\u800c\u5b89\u88c5\u5931\u8d25\u3002\u6240\u4ee5\u6211\u4eec\u8981\u8bfb\u53d6 GitLab CI \u7684 $CI_ENVIRONMENT_SLUG \u73af\u5883\u53d8\u91cf\uff0c\u5e76\u62fc\u63a5\u5230\u6700\u7ec8\u7684 Helm release name\u3002\u56e0\u6b64\u53ef\u4ee5\u8fd9\u6837\u505a\uff1a\n# ... releases: - name: api-{{ requiredEnv &#34;CI_ENVIRONMENT_SLUG&#34; }} chart: .\/deploy\/chart # ... \u5176\u5b9e helmfile.yaml \u662f\u4e2a Go template \u683c\u5f0f\u7684\u6a21\u677f\uff0c\u56e0\u6b64\u4f60\u8fd8\u53ef\u4ee5\u628a\u73af\u5883\u53d8\u91cf\u4f20\u9012\u7ed9 values\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528 if \u4e4b\u7c7b\u7684\u8bed\u6cd5\u3002\u4f8b\u5982\uff1a\n# ... releases: - name: my-release namespace: staging chart: bitnami\/redis set: - name: cluster.enabled value: {{ requiredEnv &#34;REDIS_CLUSTER_ENABLED&#34; }} \u533a\u5206\u73af\u5883 Helmfile \u63d0\u4f9b\u4e86\u540d\u4e3a environments \u7684\u914d\u7f6e\uff0c\u6b64\u5904\u5e76\u4e0d\u662f\u6307\u73af\u5883\u53d8\u91cf\uff0c\u800c\u662f\u4e00\u4e2a\u4e13\u5c5e\u4e8e Helmfile \u7684\u6982\u5ff5\u3002\u6765\u770b\u770b\u4f8b\u5b50\u3002\u9996\u5148\u521b\u5efa\u4e24\u4e2a\u6587\u4ef6\uff1a\n# environments\/staging\/values.yaml releaseName: staging-release # environment\/production\/values.yaml releaseName: production-release \u914d\u7f6e helmfile.yaml\uff1a\n# ... environments: staging: values: # \u9488\u5bf9 staging \u73af\u5883\u7684 values\uff0c\u53ef\u901a\u8fc7 {{ .Environment.Values.* }} \u8bfb\u53d6 - environments\/staging\/values.yaml production: values: # \u9488\u5bf9 production \u73af\u5883\u7684 values\uff0c\u8bfb\u53d6\u65b9\u5f0f\u76f8\u540c - environment\/production\/values.yaml releases: - name: {{ .Environment.Values.releaseName }} # \u5f15\u7528 environment values \u7684\u503c\uff08\u4f8b\u5982 staging-release \u6216 production-release\uff09 namespace: {{ .Environment.Name }} # \u5f15\u7528 envrionment \u540d\u79f0\uff08\u4f8b\u5982 staging \u6216 production\uff09 chart: bitnami\/redis values: - values\/{{ .Environment.Name }}\/values.yaml # \u6839\u636e\u73af\u5883\u540d\u79f0\u8bfb\u53d6\u4e0d\u540c\u7684 Helm values \u6587\u4ef6 {{ if eq .Environment.Name &#34;production&#34; }} # Go template \u7684 if \u8bed\u53e5 - values\/production-specified-values.yaml # \u4ec5\u7528\u4e8e production \u73af\u5883\u7684 Helm values {{ end }} \u5728\u6267\u884c helmfile \u65f6\u4f7f\u7528 -e \u9009\u9879\u5373\u53ef\u6307\u5b9a\u5b89\u88c5\u7684\u73af\u5883\uff1a\nhelmfile -e staging apply \u6ce8\u610f -e \u5fc5\u987b\u5728\u5b50\u547d\u4ee4 apply \u4e4b\u524d\uff0c\u5b83\u662f\u4e00\u4e2a\u5168\u5c40\u9009\u9879\u3002\n\u5c0f\u7ed3 \u4e0d\u5f97\u4e0d\u8bf4\uff0cHelmfile \u7684\u786e\u5f88\u7075\u6d3b\uff0c\u4f46\u91c7\u7528 Go template + YAML \u8bed\u6cd5\u7f16\u5199\u914d\u7f6e\u7684\u65b9\u5f0f\u7a0d\u6709\u4e9b\u96be\u4ee5\u9605\u8bfb\u548c\u7ef4\u62a4\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/getting-to-know-helmfile\/","summary":"<p>\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u4e86 Helm \u7684\u521d\u6b65\u4f7f\u7528\u3002\u7136\u800c\u8fd9\u4ecd\u7136\u4e0d\u80fd\u6ee1\u8db3\u6211\u53f8\u7684\u5de5\u4f5c\u6d41\uff0c\u4e3b\u8981\u95ee\u9898\u6709\uff1a<\/p>\n<ol>\n<li>Helm \u4e0d\u63d0\u4f9b <code>apply<\/code> \u547d\u4ee4\uff1b\u56e0\u6b64\u5728 CI\/CD \u573a\u666f\u4e2d\u5fc5\u987b\u8003\u8651\u5230\u5224\u65ad\u662f install \u8fd8\u662f upgrade\u3002<\/li>\n<li>\u4e0d\u65b9\u4fbf\u63a7\u5236\u5b89\u88c5\u7684 chart \u7248\u672c\uff1b\u4f8b\u5982\u6307\u5b9a\u7248\u672c\u8303\u56f4\u3001\u9501\u5b9a\u67d0\u4e00\u7248\u672c\u7b49\u3002<\/li>\n<li>Values \u5fc5\u987b\u662f\u7eaf\u6587\u672c\uff1b\u4e0d\u652f\u6301\u6a21\u677f\u6e32\u67d3\u3001\u4e0d\u65b9\u4fbf\u533a\u5206\u73af\u5883\u3002<\/li>\n<\/ol>\n<p>\u56e0\u6b64\u6211\u4eec\u9700\u8981 <code>Helm Releases as Code<\/code>\u3002\u6211\u542c\u8bf4\u8fc7\u7684\u4ea7\u54c1\u6709 <a href=\"https:\/\/github.com\/Praqma\/helmsman\" target=\"_blank\">Helmsman<\/a> \u548c <a href=\"https:\/\/github.com\/roboll\/helmfile\" target=\"_blank\">Helmfile<\/a> \u4e24\u6b3e\u3002\u76ee\u524d\u6211\u4eec\u56e2\u961f\u5df2\u7ecf\u4f7f\u7528\u540e\u8005\u4e00\u6bb5\u65f6\u95f4\uff0c\u5e76\u4e14\u6709\u56e2\u961f\u6210\u5458\u8d21\u732e\u8fc7\u90e8\u5206\u4ee3\u7801\u3002<\/p>","title":"K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u4e86\u89e3 Helmfile"},{"content":"Helm \u662f\u4e00\u6b3e\u9488\u5bf9 Kubernetes \u7684\u300c\u5305\u7ba1\u7406\u5668\u300d\uff0c\u867d\u8bf4\u79f0\u5b83\u4e3a\u5305\u7ba1\u7406\u5668\uff0c\u5176\u5b9e\u4e0e\u5e94\u7528\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u4f7f\u7528\u7684\u5305\u7ba1\u7406\u5668\u7565\u6709\u4e0d\u540c\uff0c\u540e\u8005\u7ba1\u7406\u7684\u662f\u5e94\u7528\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u7684\u4f9d\u8d56\uff0cHelm \u5219\u7ba1\u7406\u7740 Kubernetes \u4e2d\u5e94\u7528\u90e8\u7f72\u65f6\u5404\u9879\u8d44\u6e90\u7684\u4f9d\u8d56\u3002\n\u5982\u679c\u4f60\u5bf9 Kubernetes \u6709\u4e00\u5b9a\u4e86\u89e3\uff0c\u76f8\u4fe1\u4f60\u5df2\u7ecf\u5bf9 Deployment\u3001Service\u3001Ingress \u7b49\u8d44\u6e90\u6709\u4e86\u4e00\u5b9a\u8ba4\u8bc6\uff0c\u5927\u591a\u6570 Web \u5e94\u7528\u5728\u90e8\u7f72\u5230 K8s \u96c6\u7fa4\u4e0a\u65f6\u9700\u8981\u5927\u91cf\u4e0d\u540c\u7c7b\u578b\u7684\u8d44\u6e90\u3002\u4f60\u53ef\u4ee5\u5c06\u8fd9\u4e9b\u8d44\u6e90\u58f0\u660e\u7684 YAML \u6587\u4ef6\u653e\u5728\u540c\u4e00\u4e2a\u6587\u4ef6\u5939\u4e0b\u7ba1\u7406\uff0c\u4f46\u662f\u968f\u7740\u6570\u91cf\u7684\u589e\u52a0\uff0c\u5982\u4f55\u590d\u7528\u8fd9\u4e9b YAML\u3001\u5982\u4f55\u7075\u6d3b\u53c8\u4e0d\u7e41\u7410\u5730\u8c03\u6574\u914d\u7f6e\u4ee5\u9002\u5e94\u4e0d\u540c\u73af\u5883\u3001\u5982\u4f55\u5c06\u8fd9\u4e9b YAML \u4f5c\u4e3a\u4e00\u4e2a\u6574\u4f53\u7ba1\u7406\uff0c\u6210\u4e86\u4e00\u4e2a\u4e0d\u5c0f\u7684\u95ee\u9898\u3002\n\u4e8e\u662f\uff0c\u50cf Helm\u3001Ksonnet \u8fd9\u6837\u7684\u9879\u76ee\u51fa\u73b0\u4e86\u3002\u5b83\u4eec\u7684\u601d\u8def\u5927\u591a\u53ef\u4ee5\u5206\u4e3a\u4e24\u7c7b \u2014 \u6a21\u677f\u6e32\u67d3\u6d3e\u548c\u4ee3\u7801\u914d\u7f6e\u6d3e\u3002Helm \u5c5e\u4e8e\u524d\u8005\u3002\n\u5c3d\u7ba1\u6211\u4e2a\u4eba\u4e0d\u662f\u5f88\u559c\u6b22 Go template \u7684\u8bed\u6cd5\uff0c\u4ee5\u53ca\u8003\u8651\u5230 YAML \u7684\u7f29\u8fdb\u5c42\u7ea7\uff0c\u53ef\u80fd\u4e0d\u592a\u9002\u5408\u4f7f\u7528\u6a21\u677f\u5f15\u64ce\u6e32\u67d3\u3002\u4f46\u4e0d\u53ef\u5426\u8ba4\uff1a\n Helm \u662f\u76ee\u524d Kubernetes \u5708\u5185\u5e94\u7528\u6700\u5e7f\u6cdb\u7684\u8d44\u6e90\u7ba1\u7406\u5668\uff0c\u62e5\u6709\u5f3a\u5927\u7684\u793e\u533a\u548c\u751f\u6001\u3002\u4ece\u5b98\u65b9\u524d\u671f\u63a8\u5e7f\u7684 chart \u4ed3\u5e93\u63d0\u4ea4\u8bb0\u5f55\u5c31\u53ef\u4ee5\u770b\u5f97\u51fa\u6765\uff1ahttps:\/\/github.com\/helm\/charts\/commits\/master\u3002 \u6700\u8fd1\u63a8\u51fa\u7684 Helm 3.0 \u89e3\u51b3\u4e86\u4e0d\u5c11\u4e0a\u4e00\u4e2a\u5927\u7248\u672c\u4e2d\u5b58\u5728\u7684\u8bbe\u8ba1\u95ee\u9898\uff08\u4f8b\u5982 Tiller\uff09\u3002  \u56e0\u6b64\u6211\u8ba4\u4e3a Helm \u4ecd\u7136\u662f\u76ee\u524d\u7684\u6700\u4f73\u9009\u62e9\u4e4b\u4e00\u3002\n\u4e3a\u4e86\u8ba9\u8bfb\u8005\u6709\u66f4\u52a0\u76f4\u89c2\u7684\u611f\u53d7\uff0c\u63a5\u4e0b\u6765\u6211\u5c06\u7b80\u5355\u4ecb\u7ecd\u4e00\u4e0b\u4f7f\u7528 Helm \u90e8\u7f72\u5e94\u7528\u5230 Kubernetes \u7684\u5de5\u4f5c\u6d41\u3002\n\u90e8\u7f72\u793e\u533a\u63d0\u4f9b\u7684 Chart charts \u662f Helm \u7684\u6838\u5fc3\u6982\u5ff5\u4e4b\u4e00\uff0c\u5305\u542b\u7740 Kubernetes \u5e94\u7528\u6240\u9700\u7684\u8d44\u6e90\u6a21\u677f\u3002\u5728\u5b89\u88c5 chart \u65f6\u4fee\u6539 values \u7684\u503c\u5373\u53ef\u8c03\u6574\u914d\u7f6e\u53c2\u6570\u3002\n\u9996\u5148\u4f60\u53ef\u4ee5\u5728 https:\/\/hub.helm.sh\/ \u67e5\u627e\u793e\u533a\u63d0\u4f9b\u7684 charts\u3002\u5728\u5b89\u88c5\u4e4b\u524d\u9700\u8981\u6dfb\u52a0 chart repo\uff0crepo \u5185\u5305\u542b chart \u7684\u58f0\u660e\u3002\u4f8b\u5982 bitnami \u63d0\u4f9b\u7684 chart repo\uff1a\nhelm repo add bitnami https:\/\/charts.bitnami.com\/bitnami \u4ee5 Redis chart \u4e3a\u4f8b\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u5b89\u88c5\u5b83\uff0c\u8bf4\u767d\u4e86\u5c31\u662f\u90e8\u7f72 chart \u5185\u7684\u8d44\u6e90\u5230 Kubernetes \u96c6\u7fa4\uff1a\nhelm install my-release bitnami\/redis \u5b89\u88c5\u6210\u529f\u540e\u4f1a\u51fa\u73b0\u7c7b\u4f3c\u8fd9\u6837\u7684\u63d0\u793a\uff1a\nNAME: my-release LAST DEPLOYED: Mon Mar 23 22:24:12 2020 NAMESPACE: staging STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: ** Please be patient while the chart is being deployed ** Redis can be accessed via port 6379 on the following DNS name from within your cluster: ... \u5176\u4e2d\uff0cmy-release \u662f release \u540d\u79f0\u3002Releases \u4e5f\u662f Helm \u7684\u6982\u5ff5\u4e4b\u4e00\u3002\u6bcf\u6b21\u5b89\u88c5\u90fd\u4f1a\u4ea7\u751f\u65b0\u7684 release\uff0c\u66f4\u65b0\u65f6\u5219\u4f1a\u4ea7\u751f\u65b0\u7684 release revision\u3002\u4f60\u53ef\u4ee5\u4f7f\u7528 helm list \u547d\u4ee4\u67e5\u770b\u5f53\u524d\u547d\u540d\u7a7a\u95f4\u4e0b\u7684\u6240\u6709 releases\uff1a\nNAME NAMESPACE\tREVISION\tUPDATED STATUS CHART APP VERSION my-release\tstaging 1 2020-03-23 22:24:12.345011 +0800 CST\tdeployed\tredis-10.5.11\t5.0.8 \u53e6\u5916\uff0c\u5728\u6267\u884c helm install \u547d\u4ee4\u65f6\uff0c\n\u5347\u7ea7\u3001\u56de\u6eda\u4e0e\u5220\u9664 \u4f7f\u7528 helm upgrade \u547d\u4ee4\u53ef\u7528\u4e8e\u66f4\u65b0 releases\uff0c\u4f8b\u5982\u5f53\u4fee\u6539\u4e86\u67d0\u4e2a value \u7684\u503c\uff0c\u9700\u8981\u91cd\u65b0\u90e8\u7f72\u5e94\u7528\uff1a\nhelm upgrade my-release bitnami\/redis --set cluster.enabled=false \u8fd9\u91cc\u7684 --set \u6216 --values \u9009\u9879\u53ef\u4ee5\u4fee\u6539\u7279\u5b9a value \u6216\u6307\u5b9a YAML \u683c\u5f0f\u7684 values \u914d\u7f6e\u6587\u4ef6\u3002\u8fd9\u4e24\u4e2a\u9009\u9879\u540c\u6837\u9002\u7528\u4e8e helm install \u547d\u4ee4\u3002\n\u901a\u8fc7 helm history \u547d\u4ee4\u5373\u53ef\u67e5\u770b\u67d0\u4e2a release \u90e8\u7f72\u8fc7\u7684\u5386\u53f2 revisons\uff0c\u8f93\u51fa\u7c7b\u4f3c\u4e8e\uff1a\nREVISION\tUPDATED STATUS chart APP VERSION\tDESCRIPTION 1 Mon Mar 23 22:24:12 2020\tsuperseded\tredis-10.5.11\t5.0.8 Install complete 2 Tue Mar 24 00:17:34 2020\tdeployed redis-10.5.11\t5.0.8 Upgrade complete Helm \u5728\u90e8\u7f72\u65f6\u4f1a\u5c06\u4f7f\u7528 values \u6e32\u67d3\u51fa\u6765\u7684\u8d44\u6e90\u58f0\u660e\u5b58\u50a8\u5230 release revison \u4e2d\u3002\u4e5f\u5c31\u662f\u8bf4\u6211\u4eec\u6bcf\u6b21\u5b89\u88c5\u3001\u5347\u7ea7 chart \u90fd\u53ef\u56de\u9000\u3002\u5f53\u5e94\u7528\u56e0\u4e3a\u67d0\u4e9b\u539f\u56e0\u9700\u8981\u56de\u6eda\u65f6\uff0c\u4f7f\u7528 helm rollback \u53ef\u5c06\u6240\u6709\u76f8\u5173\u8d44\u6e90\u56de\u6eda\u5230\u7279\u5b9a revison \u7684\u72b6\u6001\uff1a\nhelm rollback my-release # \u56de\u6eda\u5230\u4e0a\u4e00\u4e2a revision helm rollback my-release n # \u56de\u6eda\u5230\u7b2c n \u4e2a revision \u6700\u540e\uff0c\u5728\u9700\u8981\u5378\u8f7d\u5e94\u7528\u65f6\u4f7f\u7528 helm delete \u547d\u4ee4\u5220\u9664 release \u5373\u53ef\uff1a\nhelm delete my-release \u5c0f\u7ed3 \u4ee5\u4e0a\u662f\u4f7f\u7528 Helm \u7ba1\u7406 Kubernetes \u8d44\u6e90\u7684\u5927\u81f4\u5de5\u4f5c\u6d41\u3002\u53ef\u4ee5\u770b\u51fa\uff0c\u5927\u591a\u6570\u6d41\u7a0b\u4ecd\u7136\u662f\u300c\u9762\u5411\u8fc7\u7a0b\u300d\uff0c\u800c\u4e0d\u662f\u300c\u58f0\u660e\u5f0f\u300d\u7684\uff0c\u9700\u8981\u7531\u4eba\u5de5\u8f93\u5165\u547d\u4ee4\u3001\u5224\u65ad\u662f install \u8fd8\u662f upgrade\u3002\u7406\u60f3\u7684\u5de5\u4f5c\u6d41\u5e94\u5f53\u5c06\u8fd9\u4e9b\u8fc7\u7a0b\u7f16\u5199\u6210\u914d\u7f6e\u6587\u4ef6\uff0c\u5e76\u4e14\u80fd\u591f\u826f\u597d\u5730\u96c6\u6210 CI\/CD\u3002\u8fd9\u4e00\u90e8\u5206\u6211\u4eec\u5df2\u7ecf\u6709\u4e86\u76f8\u5bf9\u6bd4\u8f83\u5b8c\u5584\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u6211\u4f1a\u5728\u4e0b\u4e00\u7bc7\u6587\u7ae0\u4e3a\u5927\u5bb6\u8be6\u7ec6\u4ecb\u7ecd\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/getting-to-know-helm\/","summary":"<p><a href=\"https:\/\/helm.sh\/\" target=\"_blank\">Helm<\/a> \u662f\u4e00\u6b3e\u9488\u5bf9 Kubernetes \u7684\u300c\u5305\u7ba1\u7406\u5668\u300d\uff0c\u867d\u8bf4\u79f0\u5b83\u4e3a\u5305\u7ba1\u7406\u5668\uff0c\u5176\u5b9e\u4e0e\u5e94\u7528\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u4f7f\u7528\u7684\u5305\u7ba1\u7406\u5668\u7565\u6709\u4e0d\u540c\uff0c\u540e\u8005\u7ba1\u7406\u7684\u662f\u5e94\u7528\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u7684\u4f9d\u8d56\uff0cHelm \u5219\u7ba1\u7406\u7740 Kubernetes \u4e2d\u5e94\u7528\u90e8\u7f72\u65f6\u5404\u9879\u8d44\u6e90\u7684\u4f9d\u8d56\u3002<\/p>\n<p>\u5982\u679c\u4f60\u5bf9 Kubernetes \u6709\u4e00\u5b9a\u4e86\u89e3\uff0c\u76f8\u4fe1\u4f60\u5df2\u7ecf\u5bf9 Deployment\u3001Service\u3001Ingress \u7b49\u8d44\u6e90\u6709\u4e86\u4e00\u5b9a\u8ba4\u8bc6\uff0c\u5927\u591a\u6570 Web \u5e94\u7528\u5728\u90e8\u7f72\u5230 K8s \u96c6\u7fa4\u4e0a\u65f6\u9700\u8981\u5927\u91cf\u4e0d\u540c\u7c7b\u578b\u7684\u8d44\u6e90\u3002\u4f60\u53ef\u4ee5\u5c06\u8fd9\u4e9b\u8d44\u6e90\u58f0\u660e\u7684 YAML \u6587\u4ef6\u653e\u5728\u540c\u4e00\u4e2a\u6587\u4ef6\u5939\u4e0b\u7ba1\u7406\uff0c\u4f46\u662f\u968f\u7740\u6570\u91cf\u7684\u589e\u52a0\uff0c\u5982\u4f55\u590d\u7528\u8fd9\u4e9b YAML\u3001\u5982\u4f55\u7075\u6d3b\u53c8\u4e0d\u7e41\u7410\u5730\u8c03\u6574\u914d\u7f6e\u4ee5\u9002\u5e94\u4e0d\u540c\u73af\u5883\u3001\u5982\u4f55\u5c06\u8fd9\u4e9b YAML \u4f5c\u4e3a\u4e00\u4e2a\u6574\u4f53\u7ba1\u7406\uff0c\u6210\u4e86\u4e00\u4e2a\u4e0d\u5c0f\u7684\u95ee\u9898\u3002<\/p>","title":"K8s \u4e0b\u7684\u5e94\u7528\u7ba1\u7406 \u2014 \u4e86\u89e3 Helm"},{"content":"\u5e73\u65f6\u9664\u4e86\u7ef4\u62a4\u516c\u53f8\u548c\u79c1\u4eba\u5728\u516c\u6709\u4e91\u7684 Kubernetes clusters \u4e4b\u5916\uff0c\u4e2a\u4eba\u7f51\u7edc\u73af\u5883\u4e0b\u8fd8\u6709\u4e9b\u9700\u8981\u8fd0\u884c\u5728\u672c\u5730\u7684 workload\uff1b\u6bd4\u5982\u7528\u4e8e\u76d1\u63a7\u672c\u5730\u8def\u7531\u8bbe\u5907\uff08~\u4f5c~ XD\uff09\u7684 Prometheus exporters \u548c\u4e00\u4e9b\u65b0\u5947\u73a9\u610f\u513f\u3002\u4e3a\u4e86\u80fd\u591f\u8fd0\u884c\u8fd9\u4e9b\u5e94\u7528\uff0c\u6211\u5728\u5bb6\u7ec4\u5efa\u4e86\u4e00\u5957\u300c\u8fb9\u7f18\u8ba1\u7b97\u96c6\u7fa4\u300d\uff0c\u6765\u770b\u770b\u662f\u600e\u4e48\u505a\u7684\u5427\u3002\n\u786c\u4ef6\u51c6\u5907 \u6211\u624b\u5934\u4e0a\u76ee\u524d\u6709\u4e00\u53f0 Raspberry Pi 3 B&#43;\uff0c\u6211\u60f3\u4f7f\u7528\u5b83\u4f5c\u4e3a Master \u8282\u70b9\uff1a\n\u548c\u4e24\u5757 Nanopi NEO 2\uff1a\n\u642d\u5efa\u96c6\u7fa4 K3s \u4e3a\u4e86\u80fd\u591f\u9002\u5e94\u8f83\u4f4e\u7684\u8ba1\u7b97\u6027\u80fd\uff0c\u6211\u9009\u62e9\u4e86\u4f7f\u7528 K3s \u90e8\u7f72 Kubernetes \u96c6\u7fa4\u3002K3s \u662f\u4e00\u6b3e Rancher \u5f00\u6e90\u7684\u8f7b\u91cf Kubernetes \u5b9e\u73b0\uff0c\u4e3b\u8981\u76ee\u6807\u4e3a\u7269\u8054\u7f51\u548c\u8fb9\u7f18\u8ba1\u7b97\u7b49\u573a\u666f\u3002\n\u5982\u679c\u4f60\u662f\u5728\u642d\u5efa\u6d4b\u8bd5\u96c6\u7fa4\uff0c\u4e0d\u59a8\u8bd5\u8bd5 Minikube \u548c MicroK8s\uff0c\u5b83\u4eec\u80fd\u591f\u63d0\u4f9b\u66f4\u52a0\u63a5\u8fd1\u751f\u4ea7\u73af\u5883\u96c6\u7fa4\u7684\u4f53\u9a8c\u3002\n\u4e0d\u540c\u4e8e\u4ee5\u4e0a\u4e24\u6b3e\u4ea7\u54c1\uff0cK3s \u9664\u4e86\u66f4\u52a0\u8f7b\u91cf\u5916\uff0c\u8fd8\u652f\u6301\u591a\u8282\u70b9\uff0c\u56e0\u6b64\u6bd4\u8f83\u7b26\u5408\u6211\u7684\u4f7f\u7528\u573a\u666f\u3002\n \u4ee5\u4e0a\u4ea7\u54c1\u7684\u8be6\u7ec6\u5bf9\u6bd4\u53ef\u53c2\u8003 \u8fd9\u7bc7\u5e16\u5b50\u3002\n K3sup K3sup \u662f\u7531 OpenFaaS \u7684\u521b\u59cb\u4eba Alex Ellis \u5f00\u53d1\u7684\u4e00\u6b3e\u5c0f\u5de5\u5177\uff0c\u53ef\u7528\u4e8e\u5feb\u901f\u90e8\u7f72 K3s \u8282\u70b9\uff0c\u4f8b\u5982\u90e8\u7f72 master node\uff1a\nk3sup install --ip &#34;$MASTER&#34; --user pi \u6267\u884c\u4ee5\u4e0a\u547d\u4ee4\uff0cK3sup \u5c06\u4ee5\u7528\u6237 pi \u7684\u8eab\u4efd\u901a\u8fc7 SSH \u8fde\u63a5 $MASTER\uff08\u4e5f\u5c31\u662f\u4f5c\u4e3a Master \u8282\u70b9\u7684\u6811\u8393\u6d3e IP \u5730\u5740\uff09\uff0c\u5728\u4e0b\u8f7d\u5e76\u5b89\u88c5 K3s \u540e\uff0cK3sup \u4f1a\u5c06\u751f\u6210\u7684 Kubeconfig \u4ece\u8fdc\u7aef\u62c9\u53d6\u5230\u672c\u5730\u7684\u5de5\u4f5c\u76ee\u5f55\u4e2d\u3002\n\u63a5\u4e0b\u6765\u90e8\u7f72 worker node\uff1a\nk3sup join --ip &#34;$WORKER&#34; --server-ip &#34;$MASTER&#34; --user pi \u968f\u540e\u5373\u53ef\u901a\u8fc7 kubectl \u7ba1\u7406\u96c6\u7fa4\u4e86\uff1a\nexport KUBECONFIG=&#34;$(pwd)\/kubeconfig&#34; kubectl get node \u5177\u4f53\u7684\u5b89\u88c5\u8fc7\u7a0b\u9650\u4e8e\u7bc7\u5e45\u4e0d\u518d\u8be6\u8ff0\uff0c\u53ef\u53c2\u8003 Alex Ellis \u7684\u8fd9\u7bc7\u535a\u5ba2\u3002\n\u4f7f\u7528 NodeAffinity \u5904\u7406\u4e0d\u540c CPU \u67b6\u6784\u95ee\u9898 \u6839\u636e\u4e0a\u56fe\u53ef\u4ee5\u53d1\u73b0\uff0c\u6811\u8393\u6d3e\u7684 CPU arch \u662f arm\uff0c\u800c NanoPi \u662f arm64\u3002\u4e3a\u4e86\u80fd\u591f\u5c06\u5bf9\u5e94\u5176\u67b6\u6784\u7684\u5bb9\u5668\u955c\u50cf\u8c03\u5ea6\u5230\u6b63\u786e\u7684\u8282\u70b9\uff0c\u4f7f\u7528 NodeAffinity \u662f\u89e3\u51b3\u65b9\u6848\u4e4b\u4e00\u3002\u4f8b\u5982\u90e8\u7f72\u5185\u7f51\u7a7f\u900f\u9879\u76ee inlets\uff1a\napiVersion: apps\/v1 kind: Deployment metadata: name: inlets-arm64 spec: selector: matchLabels: app: inlets replicas: 1 template: metadata: labels: app: inlets spec: containers: - name: inlets image: inlets\/inlets:2.6.4-arm64 # \u955c\u50cf\u4e3a arm64 \u7248\u672c args: [server] affinity: nodeAffinity: # \u5728 Pod Scheduling \u65f6\u5f3a\u5236\u8981\u6c42 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: # \u8282\u70b9\u9009\u62e9\u5668\u6570\u7ec4 - matchExpressions: # \u5339\u914d\u8282\u70b9 labels - key: kubernetes.io\/arch  # label \u540d\u79f0 operator: In  # \u8981\u6c42\u6ee1\u8db3\u4ee5\u4e0b\u4efb\u610f\u503c\u5176\u4e00 values: [arm64]  # \u53ef\u6307\u5b9a\u591a\u4e2a\u503c \u53ef\u4ee5\u770b\u5230\u6211\u4eec\u5728 Pod Spec \u5185\u5b9a\u4e49\u4e86 affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms \u5b57\u6bb5\uff0c\u503c\u4e3a NodeSelectorTerm \u6570\u7ec4\u3002\u6211\u4eec\u5b9a\u4e49\u4e86\u4e00\u6761\u89c4\u5219\u4e3a\uff1alabel kubernetes.io\/arch \u7684\u503c\u5fc5\u987b\u5b58\u5728\u4e8e\u6570\u7ec4 [arm64] \u4e2d\u3002\u672c\u4f8b\u4e2d\u53ea\u6709\u5355\u4e2a\u503c\uff0c\u56e0\u6b64\u7b49\u6548\u4e8e\uff1a\u5fc5\u987b\u7b49\u4e8e arm64\u3002\nDocker Manifests \u5982\u679c\u4f60\u60f3\u8981\u90e8\u7f72\u7684\u5e94\u7528\u955c\u50cf\u662f\u4f60\u81ea\u5df1\u6784\u5efa\u7684\u8bdd\uff0c\u90a3\u4e48\u5f3a\u70c8\u63a8\u8350\u8bd5\u8bd5\u770b Docker image manifest v2 \u7684\u7279\u6027 \u2014\u2014 \u53ef\u521b\u5efa manifest lists \u5305\u542b\u591a\u4e2a\u4e0d\u540c platforms \u548c architectures \u7684 image manifests\u3002\nDocker Client \u4e5f\u63d0\u4f9b\u4e86\u4e00\u4e2a\u5b9e\u9a8c\u6027\u7684\u547d\u4ee4 &lt;code&gt;docker manifest&lt;\/code&gt; \u6765\u521b\u5efa\u3001\u63a8\u9001 manifest lists\u3002\u6211\u7ed3\u5408\u5b9e\u4f8b\u6765\u8bf4\u8bf4\u5b83\u7684\u7528\u6cd5\u3002\n\u7531\u4e8e\u8be5\u547d\u4ee4\u76ee\u524d\u662f\u300c\u5b9e\u9a8c\u6027\u300d\u7684\uff0c\u9996\u5148\u9700\u8981\u901a\u8fc7\u73af\u5883\u53d8\u91cf\u5f00\u542f\u624d\u80fd\u591f\u4f7f\u7528\u3002\u6211\u4eec\u987a\u4fbf\u914d\u7f6e\u51e0\u4e2a\u53d8\u91cf\u5907\u7528\uff1a\nexport DOCKER_CLI_EXPERIMENTAL=enabled # \u5f00\u542f Docker CLI \u7684\u5b9e\u9a8c\u6027\u529f\u80fd export IMAGE_REPO=vendor\/app # \u955c\u50cf\u540d\u79f0\uff0c\u8bf7\u6309\u9700\u586b\u5199 export IMAGE_TAG=v1.0.0 # \u955c\u50cf tag\uff0c\u8bf7\u6309\u9700\u586b\u5199 \u5047\u8bbe\u4f60\u5df2\u7ecf\u5206\u522b\u6784\u5efa\u597d\u9488\u5bf9 arm64 \u548c arm \u7684\u955c\u50cf\uff0c\u63a5\u4e0b\u6765\u5148\u5c06\u5b83\u4eec\u63a8\u9001\u5230 registry\uff1a\ndocker push &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm64&#34; docker push &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm&#34; \u968f\u540e\u521b\u5efa manifest list \u6307\u5411\u591a\u4e2a image manifests\uff1a\ndocker manifest create --amend \\  &#34;${IMAGE_REPO}:${IMAGE_TAG}&#34; \\  # manifest list \u540d\u79f0 &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm64&#34; \\ # \u9488\u5bf9 arm64 \u7684\u955c\u50cf &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm&#34; # \u9488\u5bf9 arm \u7684\u955c\u50cf \u6700\u5173\u952e\u7684\u4e00\u6b65\u5230\u4e86\uff0c\u4e3a\u5b83\u4eec\u6dfb\u52a0\u6ce8\u89e3\u3002\u5c06\u6bcf\u4e2a manifest \u7ed1\u5b9a\u81f3\u7279\u5b9a\u7684 os \u548c arch\uff1a\n# \u6ce8\u89e3 arm64 image manifest docker manifest annotate \\  --os linux \\  # \u7cfb\u7edf\u4e3a Linux --arch arm64 \\  # \u67b6\u6784\u4e3a arm64 &#34;${IMAGE_REPO}:${IMAGE_TAG}&#34; \\  # manifest list \u540d\u79f0 &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm64&#34; # \u88ab\u6ce8\u89e3\u7684 manifest # \u6ce8\u89e3 arm image manifest docker manifest annotate \\  --os linux \\  # \u7cfb\u7edf\u540c\u4e3a Linux --arch arm \\  # \u67b6\u6784\u4e3a arm &#34;${IMAGE_REPO}:${IMAGE_TAG}&#34; \\  # manifest list \u540d\u79f0 &#34;${IMAGE_REPO}:${IMAGE_TAG}-arm&#34; # \u88ab\u6ce8\u89e3\u7684 manifest \u6b64\u65f6 manifest list \u5df2\u7ecf\u521b\u5efa\u597d\u4e86\uff0c\u53ef\u4f7f\u7528 docker manifest inspect \u547d\u4ee4\u68c0\u67e5\u4e00\u4e0b\u5177\u4f53\u4fe1\u606f\u3002\u786e\u8ba4\u65e0\u8bef\u540e\uff0c\u63a8\u9001\u5230 registry \u5373\u53ef\uff1a\ndocker manifest push --purge &#34;${IMAGE_REPO}:${IMAGE_TAG}&#34; \u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u6b64\u5904\u7684 --purge \u53c2\u6570\u662f\u5fc5\u4e0d\u53ef\u5c11\u7684\u3002\u56e0\u4e3a Docker CLI \u5e76\u6ca1\u6709\u63d0\u4f9b docker manifest remove \u6216\u662f docker manifest purge \u4e4b\u7c7b\u7684\u547d\u4ee4\u3002\u5982\u679c\u4e0d\u968f\u7740\u63a8\u9001\u76f4\u63a5\u6e05\u7406\uff0c\u90a3\u5c31\u53ea\u80fd\u5230\u672c\u5730\u7684 $HOME\/.docker\/manifests \u76ee\u5f55\u624b\u52a8\u5220\u9664\u4e86&hellip; \u867d\u7136\u65e9\u5728 2018 \u5e74\u521d\u5c31\u6709\u4eba\u9488\u5bf9\u6b64\u95ee\u9898\u63d0\u51fa issue\uff0c\u4f46\u622a\u6b62\u53d1\u7a3f\u524d\u4ecd\u6ca1\u6709\u4ed3\u5e93 member \u56de\u590d\u3002\n\u6700\u540e\uff0c\u4f7f\u7528\u521a\u521a\u521b\u5efa\u7684 manifest list \u540d\u79f0\u4ee3\u66ff\u6709\u540e\u7f00\u7684 image manifest \u540d\u79f0\u5373\u53ef\uff0c\u751a\u81f3\u53ef\u4ee5\u589e\u52a0 replicas \u7684\u6570\u91cf\uff0c\u901a\u8fc7 PodAntiAffinity \u523b\u610f\u5c06\u591a\u4e2a\u526f\u672c\u90e8\u7f72\u5728\u4e0d\u540c CPU \u67b6\u6784\u7684\u8282\u70b9\u4e0a\u800c\u65e0\u9700\u533a\u5206 image\uff1a\napiVersion: apps\/v1 kind: Deployment metadata: name: inlets spec: selector: matchLabels: app: inlets replicas: 2 template: metadata: labels: app: inlets spec: containers: - name: inlets image: inlets\/inlets:2.6.4 # \u540e\u7f00 `arm64` \u5df2\u88ab\u79fb\u9664 args: [server] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io\/arch labelSelector: matchLabels: app: inlets \u5b8c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/setup-an-edge-computing-cluster-with-different-archs-of-cpus\/","summary":"<p>\u5e73\u65f6\u9664\u4e86\u7ef4\u62a4\u516c\u53f8\u548c\u79c1\u4eba\u5728\u516c\u6709\u4e91\u7684 Kubernetes clusters \u4e4b\u5916\uff0c\u4e2a\u4eba\u7f51\u7edc\u73af\u5883\u4e0b\u8fd8\u6709\u4e9b\u9700\u8981\u8fd0\u884c\u5728\u672c\u5730\u7684 workload\uff1b\u6bd4\u5982\u7528\u4e8e\u76d1\u63a7\u672c\u5730\u8def\u7531\u8bbe\u5907\uff08~\u4f5c~ XD\uff09\u7684 Prometheus exporters \u548c\u4e00\u4e9b\u65b0\u5947\u73a9\u610f\u513f\u3002\u4e3a\u4e86\u80fd\u591f\u8fd0\u884c\u8fd9\u4e9b\u5e94\u7528\uff0c\u6211\u5728\u5bb6\u7ec4\u5efa\u4e86\u4e00\u5957\u300c\u8fb9\u7f18\u8ba1\u7b97\u96c6\u7fa4\u300d\uff0c\u6765\u770b\u770b\u662f\u600e\u4e48\u505a\u7684\u5427\u3002<\/p>","title":"\u642d\u5efa\u5f02\u6784 CPU \u7ec4\u6210\u7684\u8fb9\u7f18\u8ba1\u7b97 Kubernetes \u96c6\u7fa4"},{"content":"\u4e3a\u4e86\u80fd\u591f\u4f7f\u4ee3\u7801\u5728\u4e0d\u540c\u9879\u76ee\u590d\u7528\uff0c\u6211\u53f8\u62bd\u8c61\u3001\u7f16\u5199\u4e86\u8bb8\u591a\u79c1\u6709 libraries\u3002\u5b83\u4eec\u7684\u6e90\u4ee3\u7801\u88ab\u7edf\u4e00\u5b58\u653e\u5728 GitLab\uff0c\u7531 CI \u786e\u4fdd\u4ee3\u7801\u98ce\u683c\u4e00\u81f4\uff0c\u5e76\u6267\u884c\u5355\u5143\u6d4b\u8bd5\u548c\u9759\u6001\u68c0\u67e5\u7b49\u3002\u7531\u4e8e\u4ed3\u5e93\u6570\u91cf\u4f17\u591a\uff0c\u5982\u4f55\u6709\u6548\u5730\u7ec4\u7ec7\u548c\u7ba1\u7406 CI \u914d\u7f6e\u6210\u4e86\u95ee\u9898\u3002\u7ecf\u8fc7\u957f\u65f6\u95f4\u7684\u63a2\u7d22\u548c\u4f18\u5316\uff0c\u6211\u6574\u7406\u4e86\u4e00\u4e9b\u7ecf\u9a8c\uff0c\u5e0c\u671b\u5bf9\u4f60\u6709\u6240\u5e2e\u52a9\u3002\nYAML \u7684\u5c0f\u6280\u5de7 \u6574\u6574 70 \u591a\u9875\u7684 YAML 1.2 Specification \u5b9a\u4e49\u4e86 YAML \u7075\u6d3b\u3001\u4e30\u5bcc\u7684\u8bed\u6cd5\u3002\u8fd9\u5176\u4e2d\u4e00\u9879\u540d\u4e3a Node Anchors \u7684\u7279\u6027\u80fd\u591f\u5e2e\u6211\u4eec\u5b9e\u73b0\u7eaf YAML \u7684\u914d\u7f6e\u590d\u7528\u3002\n\u4f8b\u5982\uff1a\ndeploy production: script: - echo &#34;deploying to production&#34; only: &amp;foo_anchor variables: - $CI_COMMIT_TAG deploy staging: script: - echo &#34;deploying to staging&#34; except: *foo_anchor \u5176\u4e2d\uff0conly \u548c except \u662f\u7ed3\u6784\u76f8\u540c\u4f46\u4f5c\u7528\u521a\u597d\u76f8\u53cd\u7684\u4e00\u5bf9\u5b57\u6bb5\u3002\u4f7f\u7528 &amp; + anchor \u6807\u8bc6\u7b26\u5373\u53ef\u8bbe\u7f6e\u951a\u70b9\uff0c\u5728\u9700\u8981\u590d\u7528\u7684\u5b57\u6bb5\u586b\u5199 * + anchor \u6807\u8bc6\u7b26\u5373\u53ef\uff0c\u5b83\u4eec\u7684\u503c\u5c06\u4f1a\u4fdd\u6301\u4e00\u81f4\u3002\nYAML 1.1 \u4e2d\u8fd8\u5b9a\u4e49\u4e86 Merge Key \u7279\u6027\uff0c\u867d\u7136\u5728 YAML 1.2 \u4e2d\u5df2\u7ecf\u6ca1\u6709\u660e\u786e\u89c4\u5b9a\uff0c\u4f46\u5728 GitLab CI \u914d\u7f6e\u4e2d\u4ecd\u7136\u53ef\u4ee5\u7ee7\u7eed\u4f7f\u7528\u3002\u76f8\u6bd4\u4e4b\u4e0b\uff0c\u6211\u4eec\u66f4\u52a0\u63a8\u8350\u4f7f\u7528 extends \u5b57\u6bb5\uff0c\u56e0\u6b64\u8be5\u6b64\u5904\u4e0d\u518d\u8d58\u8ff0\u3002\nextends \u5b57\u6bb5 \u5728 GitLab CI \u914d\u7f6e\u6587\u6863\u4e2d\u63cf\u8ff0\u4e86\u4e00\u4e2a\u540d\u4e3a &lt;code&gt;extends&lt;\/code&gt; \u7684\u5b57\u6bb5\uff0c\u53ef\u7c7b\u6bd4\u5730\u7406\u89e3\u4e3a\u9762\u5411\u5bf9\u8c61\u4e2d\u7684\u300c\u7ee7\u627f\u300d\u3002\u4f8b\u5982\uff1a\n.foo_template_job: script: - echo &#34;Deploying ${DEPLOY_ENV}&#34; deploy production: extends: .foo_template_job variables: DEPLOY_ENV: production deploy staging: extends: .foo_template_job variables: DEPLOY_ENV: staging \u5176\u4e2d\uff0c.foo_template_job \u662f\u4e00\u4e2a template job\uff0c\u987e\u540d\u601d\u4e49\uff0c\u5b83\u4e0d\u4f1a\u88ab\u5f53\u4f5c\u771f\u6b63\u7684 job \u51fa\u73b0\u5728 pipelines \u4e2d\uff0c\u800c\u662f\u4f5c\u4e3a\u6a21\u677f\u88ab\u5176\u5b83 jobs \u590d\u7528\u3001\u6269\u5c55\u3002\u540c\u65f6\u6211\u4eec\u5206\u522b\u5b9a\u4e49\u4e86 deploy production \u548c deploy staging \u4e24\u4e2a job \u4ee5\u53ca\u4e0d\u540c\u7684 variables\uff0c\u6700\u7ec8\u88ab template job \u5185\u7684 script \u4f7f\u7528\u3002\n\u8fd9\u6837\u6211\u4eec\u5c31\u80fd\u8fbe\u6210\u5404\u4e2a\u73af\u5883\u53ef\u300c\u7ee7\u627f\u300d\u540c\u4e00\u4efd\u90e8\u7f72\u811a\u672c\u7684\u76ee\u7684\uff0c\u53ea\u9700\u6269\u5c55\u5e76\u4fee\u6539\u53d8\u91cf\u5373\u53ef\u3002\nextends \u8fd8\u652f\u6301\u591a\u4e2a template jobs \u4ee5\u53ca\u5728\u666e\u901a job \u4e2d\u8986\u76d6\u6a21\u677f\u5b57\u6bb5\u7b49\u7279\u6027\uff1a\n.yarn: image: node:latest before_script: - yarn install --production - export PATH=&#34;$PATH:$PWD\/node_modules\/.bin&#34; .cached: cache: key: ${CI_COMMIT_REF_SLUG} paths: - dist\/ build: extends: - .yarn - .cached image: node:12 # \u8986\u76d6 .yarn \u4e2d\u5b9a\u4e49\u7684 image script: - echo &#34;Building artifacts&#34; include \u5b57\u6bb5\u4e0e Git Subtree \u4e0a\u6587\u4e2d\u6211\u4eec\u4ecb\u7ecd\u4e86\u5982\u4f55\u5728 .gitlab-ci.yml \u4e2d\u5b9e\u73b0\u5185\u90e8\u590d\u7528\uff0c\u8fd9\u5728\u5355\u4e00\u9879\u76ee\u4e2d\u6709\u6548\u3002\u4e3a\u4e86\u80fd\u591f\u8de8\u9879\u76ee\u590d\u7528\uff0c\u6211\u4eec\u4f7f\u7528\u4e86 &lt;code&gt;include&lt;\/code&gt; \u5b57\u6bb5\u548c Git subtree \u6765\u5b9e\u73b0\u3002\n\u901a\u8fc7 include \u5b57\u6bb5\u6211\u4eec\u53ef\u4ee5\u5c06\u590d\u6742\u7684 CI \u914d\u7f6e\u62c6\u5206\u6210\u591a\u4e2a\u6587\u4ef6\uff0c\u4f8b\u5982\u7ba1\u7406\u591a\u4e2a stages\uff1a\n# .gitlab-ci.yml stages: - build - deploy include: - local: .gitlab\/build.yml # \u4ed3\u5e93\u5185\u7684\u914d\u7f6e\u6587\u4ef6\u8def\u5f84 - local: .gitlab\/deploy.yml # .gitlab\/build.yml build binaries: stage: build script: - echo &#34;Building binaries&#34; # .gitlab\/deploy.yml deploy production: stage: deploy script: - echo &#34;Deploying production&#34; \u6211\u4eec\u628a\u5e38\u7528\u7684 template jobs \u96c6\u4e2d\u5230\u4e86\u4e00\u4e2a\u540d\u4e3a ci-templates \u7684\u4ed3\u5e93\u4e2d\uff0c\u4f8b\u5982 PHP \u9879\u76ee\u5fc5\u5907\u7684 composer install\uff1a\n\u968f\u540e\u5728\u9700\u8981\u4f7f\u7528\u7684\u9879\u76ee\u4e2d\uff0c\u5c06 ci-templates \u4ed3\u5e93\u7684\u5185\u5bb9\u901a\u8fc7 subtree \u5f15\u5165\uff1a\ngit subtree add --prefix=.gitlab\/ci-templates git@gitlab:devops\/ci-templates.git master --squash \u518d\u4f7f\u7528 include \u6307\u4ee4\u5305\u542b\u5373\u53ef\uff1a\ninclude: - local: .gitlab\/ci-templates\/templates\/composer.yml php-cs-fixer: extends: .composer # Template job \u4f4d\u4e8e\u88ab include \u7684\u6587\u4ef6\u4e2d script: - php-cs-fixer fix --dry-run --diff 1&gt;&amp;2 \u5173\u4e8e subtree \u7684\u76f8\u5173\u77e5\u8bc6\u4e0d\u518d\u8d58\u8ff0\uff0c\u8bf7\u53c2\u8003\u76f8\u5173\u6587\u6863\u3002\n\u4e0d\u4f7f\u7528 Git Subtree \u7684 include \u901a\u8fc7 Git subtree \u5f15\u5165\u7684\u6587\u4ef6\u4e0d\u4f1a\u968f\u7740\u4e0a\u6e38\uff08ci-templates\uff09\u4ed3\u5e93\u7684\u66f4\u65b0\u800c\u540c\u6b65\uff0c\u9700\u8981\u6267\u884c git subtree pull \u547d\u4ee4\u5c06\u53d8\u66f4 Pull \u5230\u9879\u76ee\u4ed3\u5e93\u4e2d\u3002\u8fd9\u79cd\u65b9\u5f0f\u7684\u597d\u5904\u662f DevOps \u4fee\u6539 templates \u65f6\uff0c\u4e0d\u4f1a\u9020\u6210\u6f5c\u5728\u7684\u3001\u53ef\u80fd\u9020\u6210\u5176\u5b83\u9879\u76ee CI \u635f\u574f\u7684\u53d8\u66f4\u3002\u540c\u4e00 Git ref\uff08\u4f8b\u5982 tags \u6216 commits\uff09\u6267\u884c pipelines \u7684\u7ed3\u679c\u80fd\u591f\u4fdd\u6301\u4e00\u81f4\u3002\n\u4f46\u968f\u7740\u5f15\u7528 templates \u7684\u4ed3\u5e93\u8d8a\u6765\u8d8a\u591a\uff0c\u6bcf\u6b21\u66f4\u65b0 ci-templates \u65f6\uff0c\u6211\u4eec\u4e0d\u5f97\u4e0d\u5728\u5404\u4e2a\u9879\u76ee\u4ed3\u5e93\u5185\u624b\u52a8 pull\u3002\u968f\u7740 GitLab 11.7 \u53d1\u5e03\uff0c\u6b64\u95ee\u9898\u7ec8\u4e8e\u5f97\u5230\u4e86\u89e3\u51b3\uff0cinclude \u5b57\u6bb5\u652f\u6301\u76f4\u63a5\u5f15\u5165\u6765\u81ea\u5176\u5b83\u4ed3\u5e93\u7684 templates \u6587\u4ef6\u4e86\uff08\u53c2\u8003 &lt;code&gt;include:file&lt;\/code&gt;\uff09\u3002\u4ee5\u4e0b\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\uff1a\ninclude: - project: devops\/ci-templates # GitLab \u9879\u76ee\u5168\u79f0 file: \/templates\/composer.yml # Template \u6587\u4ef6\u5728\u4ed3\u5e93\u5185\u7684\u8def\u5f84 phpstan: extends: .composer script: - phpstan analyse --ansi \u7ed3\u8bed \u7531\u4e8e\u6211\u4eec\u5185\u90e8\u7684 PHP \u6269\u5c55\u5305 CI\/CD \u6d41\u7a0b\u6781\u4e3a\u76f8\u4f3c\u4e14\u8f83\u4e3a\u7b80\u5355\uff0c\u51fa\u73b0\u6f5c\u5728\u300c\u591a\u7c73\u8bfa\u9aa8\u724c\u6548\u5e94\u300d\u7684\u53ef\u80fd\u6027\u8f83\u4f4e\uff1b\u8003\u8651\u5230\u7ef4\u62a4\u6210\u672c\uff0c\u6211\u4eec\u6700\u7ec8\u9009\u62e9\u5728\u6269\u5c55\u5305\u4ed3\u5e93\u4f7f\u7528 include:file \u7684\u65b9\u5f0f\u5f15\u5165 templates\u3002CI\/CD \u590d\u6742\u4e25\u8c28\u7684\u9879\u76ee\u7c7b\u578b\u4ed3\u5e93\uff0c\u5219\u4fdd\u7559\u4f7f\u7528 Git subtree\uff0c\u4ee5\u964d\u4f4e\u610f\u5916\u884c\u4e3a\u7684\u53ef\u80fd\u6027\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/reuse-gitlab-ci-configs-across-projects\/","summary":"<p>\u4e3a\u4e86\u80fd\u591f\u4f7f\u4ee3\u7801\u5728\u4e0d\u540c\u9879\u76ee\u590d\u7528\uff0c\u6211\u53f8\u62bd\u8c61\u3001\u7f16\u5199\u4e86\u8bb8\u591a\u79c1\u6709 libraries\u3002\u5b83\u4eec\u7684\u6e90\u4ee3\u7801\u88ab\u7edf\u4e00\u5b58\u653e\u5728 GitLab\uff0c\u7531 CI \u786e\u4fdd\u4ee3\u7801\u98ce\u683c\u4e00\u81f4\uff0c\u5e76\u6267\u884c\u5355\u5143\u6d4b\u8bd5\u548c\u9759\u6001\u68c0\u67e5\u7b49\u3002\u7531\u4e8e\u4ed3\u5e93\u6570\u91cf\u4f17\u591a\uff0c\u5982\u4f55\u6709\u6548\u5730\u7ec4\u7ec7\u548c\u7ba1\u7406 CI \u914d\u7f6e\u6210\u4e86\u95ee\u9898\u3002\u7ecf\u8fc7\u957f\u65f6\u95f4\u7684\u63a2\u7d22\u548c\u4f18\u5316\uff0c\u6211\u6574\u7406\u4e86\u4e00\u4e9b\u7ecf\u9a8c\uff0c\u5e0c\u671b\u5bf9\u4f60\u6709\u6240\u5e2e\u52a9\u3002<\/p>","title":"\u8de8\u9879\u76ee GitLab CI \u914d\u7f6e\u590d\u7528\u4e0e\u7ba1\u7406"},{"content":"\u5ffd\u7136\u53d1\u73b0\u519c\u5386\u65b0\u5e74\u5df2\u7ecf\u8fc7\u53bb\u4e86\u4e00\u4e2a\u6708\u3002\u8fd9\u4e00\u4e2a\u6708\u6211\u5e72\u4e86\u5565\uff1f\uff01\uff1f\n\u4e00\u4e9b\u788e\u788e\u5ff5 \u4f9d\u7167\u5f80\u5e74\uff0c\u65b0\u5e74\u5047\u671f\u6211\u901a\u5e38\u4f1a\u6293\u7d27\u65f6\u95f4\u75af\u72c2\u63d0\u4ea4\u4ee3\u7801\uff0c\u5b8c\u6210\u4e2a\u4eba\u9879\u76ee\uff0c\u5b9e\u73b0\u6709\u8da3\u7684\u60f3\u6cd5\u3002\u53ef\u80fd\u662f\u4eca\u5e74\u5e74\u524d\u5b9e\u5728\u592a\u5fd9\uff0c\u51e0\u4e4e\u6ca1\u6709\u4f11\u606f\u7684\u65f6\u5019\uff0c\u75ab\u60c5\u8513\u5ef6\u53cd\u800c\u8ba9\u81ea\u5df1\u5f7b\u5e95\u653e\u677e\u4e86\u4e0b\u6765\u3002\n\u5f00\u59cb\u5728\u5bb6\u529e\u516c\u4e4b\u540e\uff0c\u4e5f\u4f8b\u5916\u5730\u6ca1\u6709\u5229\u7528\u95f2\u6687\u65f6\u95f4\u81ea\u6211\u5b66\u4e60\u3002\u6216\u8bb8\u56e0\u4e3a\u4e4b\u524d\u592a\u95f2\uff0c\u53cd\u800c\u7cbe\u529b\u5145\u6c9b\u5730\u5904\u7406\u4e86\u4e0d\u5c11\u9648\u5e74\u8001\u95ee\u9898\u3002\u81f3\u4e8e\u4e0b\u73ed\u65f6\u95f4\uff0c\u57fa\u672c\u7528\u6765\u770b\u89c6\u9891\u3001\u6253\u6e38\u620f\u3001\u6536\u62fe\u5bb6\u52a1\u4e86\ud83d\ude02\u3002\n\u662f\u7684\u6ca1\u9519\uff0c\u51e0\u4e4e\u4e0d\u78b0\u6e38\u620f\u7684\u6211\u6700\u8fd1\u5b9e\u5728\u592a\u61d2\uff0c\u5b8c\u5168\u4e0d\u60f3\u7814\u7a76\u65b0\u4e1c\u897f\uff0c\u6240\u4ee5\u5e72\u8106\u597d\u597d\u300c\u4f11\u5047\u300d\uff0c\u5f53\u4e86\u4e00\u4e2a\u6708\u7684\u54b8\u9c7c\u3002\n\u5927\u5b66\u6bd5\u4e1a\uff08\u5e94\u5f53\uff09\u7684 22 \u5c81 \u4eca\u5e74\u53ef\u80fd\u56e0\u4e3a\u751f\u65e5\u5f53\u5929\u592a\u7f3a\u4e4f\u6c1b\u56f4\uff0c\u665a\u4e0a\u4f3c\u4e4e\u5403\u7684\u662f\u6ce1\u9762\uff0c\u6240\u4ee5\u5728\u793e\u4ea4\u5e73\u53f0\u7684\u611f\u53f9\u4e5f\u5077\u61d2\u514d\u4e86\u3002\n\u4e5f\u6709\u53ef\u80fd\u662f\u4e0d\u77e5\u9053\u8bf4\u4ec0\u4e48\u3002\u8fd9\u4e9b\u300c\u4eba\u4e3a\u300d\u8d4b\u4e88\u542b\u4e49\u7684\u65e5\u5b50\uff0c\u4e5f\u53ea\u662f\u5e73\u6de1\u7684\u4e00\u5929\u800c\u5df2\u3002\u7f3a\u4e86\u300c\u4eba\u4e3a\u300d\u7684\u70d8\u6258\uff0c\u66b4\u9732\u65e0\u9057\u3002\n\u5c11\u4e86\u60ca\u559c\u548c\u6109\u60a6\uff0c\u591a\u4e86\u4e00\u70b9\u70b9\u7684\u6050\u60e7 \u2014\u2014 \u5e74\u9f84\u7684\u6050\u60e7\u3002\u8fd9\u4e48\u8bf4\u53ef\u80fd\u4f1a\u88ab\u6253\uff0c\u54b3\u54b3\u3002\u867d\u7136\u622a\u81f3\u76ee\u524d\u6211\u4ecd\u7136\u662f\u53c2\u52a0\u5de5\u4f5c\u4ee5\u6765\u5e74\u9f84\u6700\u5c0f\u7684\u540c\u4e8b\u3002\u4f46\u7559\u7ed9\u6211\u7684\u65f6\u95f4\u5df2\u7ecf\u4e0d\u591a\u4e86\u3002\n22 \u5c81\uff0c\u540c\u9f84\u4eba\u4eca\u5e74\u8be5\u4ece\u672c\u79d1\u6bd5\u4e1a\u4e86\u3002\n\u771f\u7684\u98de\u5feb\uff0c\u4e00\u8f6c\u773c\u604d\u7136\u8fd8\u4ee5\u4e3a\u81ea\u5df1\u624d\u5341\u516b\u5c81\uff0c\u521a\u521a\u62ff\u5230\u7b2c\u4e00\u4efd Offer\uff0c\u521a\u521a\u4e0e\u9ad8\u8003\u5b8c\u7684\u540c\u5b66\u78b0\u9762\u3002\u867d\u7136\u6280\u672f\u6c34\u5e73\u5df2\u7ecf\u6709\u98de\u8dc3\u5f0f\u7684\u8fdb\u6b65\uff0c\u4f46\u603b\u662f\u62c5\u5fc3\u4e0d\u591f\u4f18\u79c0\uff0c\u4e0d\u591f\u90a3\u4e2a\u5341\u516b\u5c81\u7684\u6211\u60f3\u8c61\u5f97\u4f18\u79c0\u3002\n\u8bb0\u5f97\u67d0\u6bb5\u65f6\u95f4\u6211\u4e00\u76f4\u5fc3\u5fc3\u5ff5\u5ff5\u4e00\u4e2a\u4e2d\u671f\u76ee\u6807\uff1a\u5728\u540c\u9f84\u4eba\u5927\u5b66\u6bd5\u4e1a\u7684\u90a3\u4e00\u5e74\u8981\u6709\u8db3\u591f\u7684\u80fd\u529b\u7529\u5f00\u4ed6\u4eec\u3002\u81f3\u4e8e\u5177\u4f53\u7684\u8bc4\u5224\u6807\u51c6\u662f\u4ec0\u4e48\uff0c\u6211\u4e00\u76f4\u6ca1\u6709\u4ed4\u7ec6\u601d\u8003\u8fc7\u3002\u56e0\u4e3a\u6211\u77e5\u9053\u81c6\u60f3\u9065\u8fdc\u7684\u7ec6\u8282\uff0c\u4e0d\u5982\u7acb\u523b\u91c7\u53d6\u884c\u52a8\uff0c\u65f6\u523b\u5b66\u4e60\u3001\u4e0d\u65ad\u5b66\u4e60\u3002\u968f\u7740\u622a\u6b62\u65e5\u671f\u8d8a\u6765\u8d8a\u8fd1\uff0c\u6211\u5bf9\u81ea\u5df1\u7684\u5b9a\u4f4d\u4ece\u62bd\u8c61\u9010\u6e10\u6210\u4e3a\u73b0\u5b9e\uff0c\u76ee\u6807\u7684\u300c\u7ec8\u70b9\u7ebf\u300d\u4e5f\u4f1a\u6162\u6162\u6e05\u6670\u8d77\u6765\u3002\n\u6211\u60f3\uff0c\u6211\u5e94\u8be5\u662f\u505a\u5230\u4e86\u3002\u90a3\u65f6\u7684\u60f3\u6cd5\u4e0d\u8fc7\u662f\uff1a\n \u6211\u4e0d\u5199\u91cd\u590d\u7684\u4f5c\u4e1a\u4e0d\u4ee3\u8868\u6211\u8d2a\u73a9 \u6211\u80cc\u4e0d\u8fc7\u5386\u53f2\u4e0d\u4ee3\u8868\u6211\u5b66\u4e60\u80fd\u529b\u5f31 \u6211\u4e0d\u89c9\u5f97\u6211\u6bd4\u540c\u9f84\u4eba\u5dee \u65e2\u7136\u8dd1\u4e0d\u4e0b\u6765 1000 \u7c73\uff0c\u6211\u9009\u62e9\u4e0d\u8dd1\uff0c\u6211\u8981\u4e70\u8f86\u8f66\u4ee3\u66ff\u6211\u8dd1 \u6211\u8981\u8bc1\u660e\u81ea\u5df1\u7684\u9009\u62e9\u662f\u5bf9\u7684  \u4ee5\u53ca\uff1a\n\u6ca1\u4eba\u80fd\u4e00\u76f4\u5f3a\u8feb\u6211\u505a\u6211\u4e0d\u613f\u610f\u505a\u7684\u4e8b\u3002\n\u5982\u679c\u518d\u89c1\u5230\u5f53\u5e74\u7684\u4eba\u4eec\uff0c\u6211\u4f1a\u544a\u8bc9\u4ed6\uff1a\u8bf7\u5c0a\u91cd\u5e76\u5f15\u5bfc\u4f60\u7684\u5b66\u751f\uff0c\u522b\u7ad9\u5728\u9053\u5fb7\u7684\u5236\u9ad8\u70b9\u4e0a\uff0c\u4ee5\u4e3a\u81ea\u5df1\u6c38\u8fdc\u90fd\u662f\u6b63\u786e\u7684\u3002\n\u6700\u540e \u6211\u7b97\u4e0d\u4e0a\u4f7c\u4f7c\u8005\uff0c\u4f46\uff1a\n \u505a\u4e0d\u5f97\u65f7\u4e16\u7684\u9038\u624d\uff0c\n\u53ea\u505a\u4f60\u5929\u5730\u95f4\u7684\u4f1e\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/thoughts-after-my-22th-birthday\/","summary":"<p>\u5ffd\u7136\u53d1\u73b0\u519c\u5386\u65b0\u5e74\u5df2\u7ecf\u8fc7\u53bb\u4e86\u4e00\u4e2a\u6708\u3002\u8fd9\u4e00\u4e2a\u6708\u6211\u5e72\u4e86\u5565\uff1f\uff01\uff1f<\/p>","title":"22 \u5c81\u7684\u6742\u8c08"},{"content":"The VPN provider of Nanjing University has recently been changed to Sangfor, which is one of the biggest company who provides the corporate SDN, VPN and other enterprise network solutions in China. Although, the SSL VPN client from Sangfor is extremely hard to use - Changing the default DNS server without any notification, hijacking all UDP packet that dport is 53, even removing all the default route generated from the CIDR of interfaces which prevents the client connect to any LAN devices except **.**.**.1. These issues have been described as &ldquo;features&rdquo; of their products from a training manual that I found in Baidu Wenku.\nBy digging into the VPN client for several days, I finally give up with trying to add some kind of plugins or extensions, because they don&rsquo;t allow to. The client binary comes with a daemon, which will watch the route table and DNS settings. Even when I use chattr to avoid any changes of \/etc\/resolv.conf, both the daemon and VPN client won&rsquo;t work but only print an error.\nAs their perspective, I totally understand they could always facing unusual environment from the clients. But for me, These all whatever issues or features are obstruction and messing up my development configuration.\nSo I ended this up by launching a independent VM in my home cluster with V2Ray and Sangfor SSL VPN client installed. The V2Ray is running under serving mode, accept and handle incoming traffic from the real client as well as my Mac, then relay the traffic from the VM which is also in the VPN. Thus, when I ever need the campus network, all I have to do is connecting to the proxy provided by V2Ray, using SwitchyOmega, Surge or any other SOCKS5 compatible tool - without this terrible client.\nHere are the scripts that I use.\n# Install gnome and GUI in order to run VPN client. apt install x-window-system-core apt install gnome-core apt install libgtk2.0-0:i386 # Add policy-based routing rules and update the routing tables. ip route add table 100 default via &lt;GATEWAY&gt; dev eth0 ip route add table 200 default dev tun0 # proto kernel scope link src 2.0.0.118 # All traffic matched fwmark == 254 should be routed to table 200, and table 100 for the others. ip rule add from all table 100 ip rule add fwmark 254 table 200 # Delete DNS hajacking iptables rule. iptables -t nat -D OUTPUT -p udp -m udp ! --sport 7789 --dport 53 -j DNAT --to-destination 127.0.0.1:5373 ip rule add to 114.114.114.114 table main # Install dnsmasq and relay all local dns queries to 114.114.114.114 no-resolv server=114.114.114.114 Here is a example V2Ray configration of it. Please pay attention to outbounds[].streamSettings.sockopt.mark was set to 254, which is the same value from routing policies described ahead.\n{ &#34;log&#34;: { &#34;error&#34;: &#34;\/var\/log\/v2ray.log&#34;, &#34;loglevel&#34;: &#34;warning&#34; }, &#34;inbounds&#34;: [ { &#34;protocol&#34;: &#34;vmess&#34;, &#34;port&#34;: &lt;PORT&gt;, &#34;settings&#34;: { &#34;clients&#34;: [ { &#34;id&#34;: &#34;&lt;USER_ID&gt;&#34; } ] } } ], &#34;outbounds&#34;: [ { &#34;protocol&#34;: &#34;freedom&#34;, &#34;tag&#34;: &#34;direct&#34;, &#34;streamSettings&#34;: { &#34;sockopt&#34;: { &#34;mark&#34;: 254 } } } ] } ","permalink":"https:\/\/wi1dcard.dev\/posts\/connect-to-sangfor-ssl-vpn-without-the-terrible-client\/","summary":"<p>The VPN provider of Nanjing University has recently been changed to Sangfor, which is one of the biggest company who provides the corporate SDN, VPN and other enterprise network solutions in China. Although, the <a href=\"https:\/\/vpn.nju.edu.cn\/portal\/#!\/login\" target=\"_blank\">SSL VPN client<\/a> from Sangfor is extremely hard to use - Changing the default DNS server without any notification, hijacking all UDP packet that dport is 53, even removing all the default route generated from the CIDR of interfaces which prevents the client connect to any LAN devices except <code>**.**.**.1<\/code>. These issues have been described as &ldquo;features&rdquo; of their products from a training manual that I found in <a href=\"https:\/\/wenku.baidu.com\/view\/51fec468a45177232f60a2d2.html\" target=\"_blank\">Baidu Wenku<\/a>.<\/p>","title":"Connect to Sangfor SSL VPNs Without the Terrible Client"},{"content":"\u8f6c\u773c\u95f4\u5230\u4e86 2019 \u5e74\u672b\uff0c\u8fd8\u8bb0\u5f97\u53bb\u5e74\u4e5f\u5199\u8fc7\u4e00\u7bc7\u7c7b\u4f3c\u7684 \u535a\u5ba2\uff1b\u8ba1\u5212\u4eca\u5e74\u7684\u300c\u5e74\u7ec8\u603b\u7ed3\u300d\u86ee\u4e45\u4e86\uff0c\u53ea\u662f\u89c9\u5f97\u65f6\u95f4\u8fd8\u65e9\u4fbf\u4e00\u76f4\u6ca1\u6709\u52a8\u624b\uff0c\u76f4\u5230\u4eca\u5929\u624d\u604d\u7136 \u2014\u2014 \u5df2\u7ecf\u662f 2019 \u5e74\u6700\u540e\u4e00\u5929\u4e86\u3002\n2019 \u5e74\u7684\u76ee\u6807 \u2014\u2014 \u534a\u8fbe\u6210 \u82e5\u662f\u6982\u62ec\u53bb\u5e74\u5b9a\u4e0b\u7684\u76ee\u6807\uff1a\n \u6280\u672f\u65b9\u9762\uff1a\u7ee7\u7eed\u6df1\u5165\u540e\u7aef\u9886\u57df \u2014\u2014 \u8fbe\u6210\u3002 \u989d\u5916\u6280\u80fd\uff1a\u63d0\u5347\u82f1\u8bed\u6c34\u5e73 \u2014\u2014 \u534a\u8fbe\u6210\uff0c\u867d\u7136\u6709\u6240\u63d0\u9ad8\uff08\u81f3\u5c11\u8ddf\u8001\u5916\u53d1\u90ae\u4ef6\u3001\u804a Slack \u4e0d\u602f\u573a\uff09\uff0c\u4f46\u8fd8\u662f\u6ca1\u6709\u8fbe\u5230\u300c\u8d28\u7684\u98de\u8dc3\u300d\u3002 \u751f\u6d3b\u65b9\u9762\uff1a***\uff0c\u4ee5\u53ca\u953b\u70bc\u53a8\u827a \u2014\u2014 \u8fbe\u6210\uff01 \u5176\u5b83\uff1a\u8eab\u4f53\u5065\u5eb7 \u2014\u2014 \u534a\u8fbe\u6210\uff0c\u8170\u75bc\u817f\u9ebb\u66f4\u4e25\u91cd\u4e86&hellip;  \u8bb2\u771f\uff0c\u4f5c\u4e3a\u4e00\u4e2a\u7a0b\u5e8f\u5458\uff0c\u6211\u5f3a\u70c8\u5efa\u8bae\u5728\u4ee3\u7801\u4e4b\u5916\u57f9\u517b\u8d77\u5176\u5b83\u7684\u7231\u597d\uff0c\u751a\u81f3\u662f\u6280\u80fd\u3002\u5f53\u7136\u6211\u5e76\u4e0d\u53cd\u5bf9\u5728\u804c\u4e1a\u9886\u57df\u6df1\u7a76\uff08\u76f8\u53cd\uff0c\u4e0b\u6587\u4f1a\u63d0\u5230\u54ea\u4e2a\u65b9\u9762\u300c\u6d6a\u8d39\u300d\u4e86\u6211\u4e00\u6574\u5e74\u7684\u6280\u672f\u5411\u4e1a\u4f59\u7cbe\u529b\ud83d\ude02\uff09\uff0c\u53ea\u4e0d\u8fc7\u4eca\u5e74\u5bf9\u4e8e\u4ee3\u7801\u4ee5\u5916\u7684\u4e16\u754c\u6709\u4e86\u8bb8\u591a\u65b0\u7684\u8ba4\u8bc6\uff0c\u5b83\u4eec\u771f\u7684\u4f1a\u7ed9\u6211\u5e26\u6765 \u4e0d\u4e00\u6837\u7684 \u5e78\u798f\u611f\u548c\u6210\u5c31\u611f\uff0c\u8fd9\u662f\u94bb\u7814\u6280\u672f\u6240\u4f53\u9a8c\u4e0d\u5230\u7684\u3002\n2019 \u5e74\u6211\u5e72\u4e86\u5565 \u6211\u7528\u4e00\u4e9b\u811a\u672c\u628a\u4eca\u5e74\u6240\u6709\u7684 Git Commits \u5168\u90e8\u5bfc\u51fa\u6210 CSV\uff0c\u7136\u540e\u518d\u4f7f\u7528 Office 365 Excel \u5206\u6790\uff0c\u53d1\u73b0\u4e86\u4e00\u4e9b\u6709\u8da3\u7684\u7ed3\u679c\u3002\n\u5e74\u5ea6\u62a5\u544a\uff08\u4ec5\u4f5c\u5a31\u4e50\uff09  2019 \u5e74\u6211\u4e00\u5171\u63d0\u4ea4\u4e86 1991 \u6b21\uff0c\u5176\u4e2d\u516c\u53f8\u4ed3\u5e93 1024 \u6b21\uff0c\u4e2a\u4eba\uff08\u5305\u62ec\u79c1\u6709\u548c\u5f00\u6e90\uff09\u4ed3\u5e93 967 \u6b21\u3002 \u5728\u516c\u53f8\u4ed3\u5e93\u7684\u63d0\u4ea4\u4e2d\uff0c\u6709 851 \u6b21\u662f\u5728\u5de5\u4f5c\u65f6\u95f4\uff0c\u7ea6\u5360 83%\uff1b\u76f8\u53cd\uff0c\u4e2a\u4eba\u4ed3\u5e93\u6709 798 \u6b21\u63d0\u4ea4\u662f\u5728\u4e0b\u73ed\u540e\u6216\u4f11\u606f\u65e5\uff0c\u7ea6\u5360 83%\uff0c\u5b8c\u7f8e\u7684\u914d\u6bd4\u3002 \u8ba9\u6211\u6ca1\u60f3\u5230\u7684\u662f\uff0c\u4e00\u5929 24 \u5c0f\u65f6\uff0c\u5404\u4e2a\u5c0f\u65f6\u6211\u90fd\u66fe\u6709\u8fc7\u63d0\u4ea4\uff08\u4ec5\u4e2a\u4eba\u4ed3\u5e93\uff09\uff1a  6 \u6708 24 \u53f7\u6211\u4f3c\u4e4e\u7761\u5f97\u5f88\u65e9\uff0c\u6700\u540e\u4e00\u6b21\u63d0\u4ea4\u5728 21:17\uff0c\u63a5\u7740 25 \u53f7\u7684\u7b2c\u4e00\u6b21\u63d0\u4ea4\u51fa\u73b0\u5728 5:23\u3002 \u51fa\u73b0\u5728 \u51cc\u6668 4 \u70b9 \u7684\u53ea\u6709\u4e24\u6b21\u63d0\u4ea4\uff0c\u6765\u6e90\u4e8e 2 \u6708 13 \u53f7\u5c1d\u8bd5 Rust \u5199\u7684\u4e00\u4e2a Demo \u9879\u76ee\uff0c\u7136\u800c\u540e\u6765\u8fd8\u662f\u6682\u505c\u4e86 Rust \u5b66\u4e60\u8ba1\u5212\u3002 \u51fa\u73b0\u5728 \u51cc\u6668 3 \u70b9 \u7684\u4e5f\u53ea\u6709\u4e24\u6b21\u63d0\u4ea4\uff0c\u6765\u6e90\u4e8e\u79c1\u4eba\u5907\u4efd\u4ed3\u5e93\uff0c\u770b\u8d77\u6765\u4f3c\u4e4e\u6211\u5728 6 \u6708 26 \u53f7\u534a\u591c\u5907\u4efd\u4e86\u4e00\u4e0b\u7535\u8111\u3002 \u6392\u9664\u4ee5\u4e0a\u7ed3\u679c\uff0c\u6211\u71ac\u591c\u809d\u5230\u6700\u665a\u7684\u4e00\u6b21\u662f 5 \u6708 18 \u65e5 2:44 \u6539\u8fdb kexue-gateway\u3002 \u5728 1 \uff5e 2 \u70b9\u6211\u66fe\u63d0\u4ea4\u8fc7 42 \u6b21\uff1b\u79d1\u5b66\u4e0a\u7f51\u76f8\u5173 24 \u6b21\uff0c\u535a\u5ba2 10 \u6b21\uff0cKubernetes \u76f8\u5173 7 \u6b21\u3002 \u665a\u4e0a\u6548\u7387\u6700\u9ad8\u7684\u65f6\u95f4\u662f 21 \uff5e 22 \u70b9\uff0c\u56e0\u4e3a 18 \u70b9\u949f\u603b\u63d0\u4ea4 27 \u6b21\uff0c19 \u70b9 60 \u6b21\uff0c20 \u70b9 99 \u6b21\uff0c21 \u70b9 138 \u6b21\uff0c10 \u70b9 148 \u6b21\uff0c11 \u70b9 70 \u6b21\uff0c12 \u70b9\u53ea\u5269 52 \u6b21\u4e86\u3002    \u5de5\u4f5c\u65f6\u95f4\u7ebf  1\u30012 \u6708\u4efd\u6211\u8fd8\u5728\u4e0e GitLab CI\u3001Ansible\u3001Cloud-init \u594b\u6218\uff0c\u4e3b\u8981\u7cbe\u529b\u96c6\u4e2d\u5728\u90e8\u7f72 Prometheus\u3001Grafana \u7b49\u76d1\u63a7\u3001\u9884\u8b66\u9879\u76ee\u4e0a\u3002 3 \u6708\u5f00\u59cb\u6df1\u5165\u5b66\u4e60 Terraform\u3002 4 \u6708\u53c8\u6298\u817e\u76d1\u63a7\uff0c\u987a\u4fbf\u6df1\u5165\u7814\u7a76\u4e86 Laravel \u961f\u5217\u5e76\u5e94\u7528\u5230\u7ebf\u4e0a\u3002 5 \u6708\u4f7f\u7528 Golang \u5f00\u53d1\u5b9a\u65f6\u4efb\u52a1\u5931\u8d25\u544a\u8b66\uff0c\u540c\u65f6\u5c06\u539f\u672c\u4eba\u5de5\u7ef4\u62a4\u7684 Cronitor \u914d\u7f6e\u8fc1\u79fb\u5230 Terraform\uff0c\u591a\u4e8f\u4e86\u6211\u53f8\u540c\u4e8b\u5f00\u53d1\u7684 terraform-provider-cronitor\u3002 \u8f6c\u6298\u70b9\uff1a5 \u6708\u5e95\u7ec8\u4e8e\u5f00\u59cb\u771f\u6b63\u63a5\u89e6 Kubernetes\uff01 6 \u6708\u5b8c\u6574\u5730\u68b3\u7406\u4e86\u516c\u53f8\u7f51\u7edc\u62d3\u6251\uff0c\u90e8\u7f72\u4e86\u65b0\u7684 UniFi \u5168\u5bb6\u6876\u548c\u4e00\u53f0\u5de8\u6c89\u7684\u673a\u67dc\uff0c\u5e76\u642d\u5efa\u4e86\u4e00\u5957\u5907\u7528\u7684\u7f51\u5173\u3002 6 \u6708\u5e95\u6211\u4eec\u53c8\u628a\u9ed1\u76d2\u63a2\u9488\u76d1\u63a7 StatusCake \u914d\u7f6e\u8fc1\u79fb\u5230\u4e86 Terraform\u3002 7 \u6708\u5927\u6279\u91cf\u8fc1\u79fb Kubernetes\uff0c\u4f9d\u7a00\u8bb0\u5f97\u90a3\u65f6\u5019\u72c2\u5220 Cloud-init \u673a\u5668\u914d\u7f6e\u7684\u9178\u723d\u3002 7 \u6708\u4e0b\u65ec\u5230 8 \u6708\u4e0a\u65ec\uff0c\u63a5\u8fd1\u4e00\u6574\u6708\u7684\u65f6\u95f4\u6211\u90fd\u505c\u7559\u5728\u300c\u88ab PHPStan \u5751\uff08\u5176\u5b9e\u662f\u88ab\u9057\u4f20\u4ee3\u7801\uff09\u300d-&gt;\u300c\u4ece\u5751\u91cc\u722c\u51fa\u6765\u300d-&gt;\u300c\u518d\u8e29\u65b0\u5751\u300d\u7684\u5faa\u73af\u4e2d\uff1b\u7ed9\u51e0\u5341\u4e2a\u79c1\u6709\u5305\u52a0 PHPStan \u8fd8\u8981\u4fee\u590d\u62a5\u9519\uff0c\u771f\u662f\u4f53\u529b\u6d3b\u3002 8 \u6708\u5269\u4f59\u7684\u65f6\u95f4\u76f4\u5230 10 \u6708\u5e95\uff0c\u53ef\u8c13\u662f\u5c0f\u5b87\u5b99\u7206\u53d1\uff0c\u5229\u7528 Helm \u548c Helmfile \u90e8\u7f72\u4e86\u4e0d\u5c11\u5e94\u7528\u5230 Kubernetes\uff0c\u7ec8\u4e8e\u79f0\u5f97\u4e0a\u5165\u95e8\u4e86\uff1b\u8fd8\u987a\u4fbf\u8c03\u7814\u4e86 Helm Secrets \u914d\u5408 Sops \u7684 Git \u4ed3\u5e93\u5185\u5bc6\u94a5\u7ba1\u7406\u65b9\u6848\uff0c\u6700\u7ec8\u5b9e\u65bd\u4e0a\u7ebf\u5e76\u4e14\u4e00\u76f4\u7528\u5230\u73b0\u5728\u3002 \u8f6c\u6298\u70b9\uff1a10 \u6708\u5e95\u5f00\u59cb\u63a5\u624b IT \u76f8\u5173\u5de5\u4f5c\uff0c\u4e0d\u4ec5\u9700\u8981\u7ef4\u62a4\u516c\u53f8\u5458\u5de5\u6743\u9650\uff08\u4f8b\u5982 Azure AD\u3001Office 365\u3001Atlassian \u7b49\uff09\uff0c\u8fd8\u5305\u62ec\u5904\u7406\u6765\u81ea\u7f8e\u56fd\u529e\u516c\u5ba4\u7684 IT Tickets \u4ee5\u53ca Onboarding Request\u3002 11 \u6708\u91cd\u65b0\u68b3\u7406\u4e86\u5e74\u4e45\u5931\u4fee\u7684\u516c\u53f8 VPN \u63a5\u5165\u70b9\uff0c\u5176\u5b83\u5927\u90e8\u5206\u65f6\u95f4\u90fd\u7528\u5728\u4e86\u7814\u7a76 Salesforce\u3001\u4f7f\u7528 TypeScript \u5f00\u53d1\u81ea\u52a8\u5316\u5de5\u5177\uff0c\u5c06 DiscoveryData \u7684 Sales leads \u5bfc\u5165\u5230 Salesforce\uff0c\u4ee5\u4f9b\u7f8e\u56fd Sales Team \u4f7f\u7528\u3002 12 \u6708\u51e0\u4e4e\u4e00\u76f4\u5728\u5904\u7406\u5404\u79cd\u5404\u6837\u7684 IT Tickets\uff0c\u7f8e\u56fd\u90a3\u8fb9\u7684\u62db\u4eba\u901f\u5ea6\u5b9e\u5728\u592a\u5feb\u4e86\u3002\u53e6\u5916\uff0c\u4f7f\u7528 Golang \u5f00\u53d1\u4e86 PHP-CS-Fixer \u89c4\u5219\u81ea\u52a8\u66f4\u65b0\u673a\u5668\u4eba\uff0c\u4fdd\u8bc1\u6570\u5341\u4e2a\u6269\u5c55\u5305\u7684\u4ee3\u7801\u98ce\u683c\u4e00\u81f4\uff1b\u4ee5\u53ca\u5f7b\u5e95\u5e9f\u5f03\u4e86\u4e0d\u7a33\u5b9a\u7684 StatusCake\uff0c\u8f6c\u6295 Pingdom\u3002  \u53ef\u4ee5\u770b\u51fa\uff0c\u6574\u6574\u4e00\u5e74\u4e0b\u6765\u63a5\u89e6\u7684\u8de8\u5ea6\u975e\u5e38\u5e7f\uff0c\u4ece\u5e74\u521d\u7684 Ansible\u3001Terraform \u5230\u540e\u6765 Kubernetes\uff0c\u518d\u5230\u5e74\u672b\u7684 IT\u3001Office 365 \u7b49\uff0c\u4eca\u5e74\u5b9e\u5728\u662f\u5b66\u5230\u592a\u591a\u4e4b\u524d\u6ca1\u6709\u673a\u4f1a\u5c1d\u8bd5\uff0c\u751a\u81f3\u662f\u5b8c\u5168\u6ca1\u6709\u542c\u8bf4\u8fc7\u7684\u77e5\u8bc6\u3002\u867d\u7136\u5176\u4e2d\u4e5f\u6709\u75b2\u5026\u548c\u52b3\u7d2f\uff0c\u4f46\u7279\u522b\u611f\u8c22 RightCapital\uff0c\u5728\u6211\u53f8\u5de5\u4f5c\u771f\u7684\u975e\u5e38\u5e78\u798f\u3002\n\u4ed4\u7ec6\u60f3\u60f3\uff0c\u6211\u6240\u5728\u7684 DevOps Team \u66f4\u50cf\u662f\u57fa\u7840\u67b6\u6784\u90e8 \u2014\u2014 \u5e73\u65f6\u4e0d\u4ec5\u6d89\u53ca\u5230\u524d\u540e\u7aef\u3001\u5e94\u7528\u90e8\u7f72\u3001\u7f51\u7edc\u90e8\u7f72\u3001\u8fd0\u7ef4\u4fdd\u969c\u3001\u6743\u9650\u7ba1\u7406\uff0c\u8fd8\u9700\u8981\u8de8\u65f6\u533a\u8ddf Support Team\u3001Sales Team \u6c9f\u901a\uff0c\u4efb\u52a1\u8270\u5de8\u5440\ud83d\ude01\u3002\n\u4e2a\u4eba\u6210\u957f\u65f6\u95f4\u7ebf \u76f8\u6bd4\u4e4b\u4e0b\uff0c\u901a\u8fc7\u4e2a\u4eba\u4ed3\u5e93\u5206\u6790\u51fa\u7684\u65f6\u95f4\u7ebf\u5c31\u7b80\u5355\u591a\u4e86\uff0c\u540c\u4e00\u6bb5\u65f6\u95f4\u5185\u6211\u57fa\u672c\u90fd\u4f1a\u56f4\u7ed5\u5728\u540c\u4e00\u4e3b\u9898\u6df1\u6316\u3002\n 1\u30012 \u6708\u4e00\u76f4\u5728\u6574\u7406\u548c\u7f16\u5199\u535a\u5ba2\uff0c\u5305\u62ec\u4f18\u5316 CI\u3001\u8c03\u6574\u9875\u9762\u5e03\u5c40\u7b49\u3002 2 \u6708\u5e95\u5f00\u59cb\u300cLaravel \u90e8\u7f72\u8bfe\u7a0b\u300d\u7cfb\u5217\uff0c\u53ef\u60dc\u4e0d\u4e45\u540e\u4fbf\u653e\u5f03\u3002 \u653e\u5f03\u7684\u539f\u56e0\u4e4b\u4e00\u5c31\u662f \u6d6a\u8d39\u6389\u6211\u4eca\u5e74\u51e0\u4e4e\u6240\u6709\u4e1a\u4f59\u65f6\u95f4\u7684\u5927\u5751 \u2014\u2014 \u79d1\u5b66\u4e0a\u7f51\u3002\u7531\u4e8e\u5e02\u9762\u4e0a\u7684\u8def\u7531\u5668\u6027\u80fd\u90fd\u5f88\u5dee\uff08\u76f8\u4fe1\u6ca1\u6709\u5382\u5bb6\u751f\u4ea7\u8def\u7531\u5668\u7684\u65f6\u5019\u8003\u8651\u5230\u8fd9\u7c7b\u7528\u9014\uff09\uff0c\u800c\u90a3\u4e9b\u73a9\u8f6f\u8def\u7531\u7684\u65b9\u6848\u51e0\u4e4e\u90fd\u662f\u9760\u5237\u7b2c\u4e09\u65b9 OpenWrt \u7b49\u56fa\u4ef6\uff0c\u914d\u5408\u7b2c\u4e09\u65b9\u63d2\u4ef6\u5b9e\u73b0\uff0c\u4e14\u4e0d\u8bf4\u6211\u66fe\u7ecf\u73a9\u8fc7\u7684\u6539\u7248\u6885\u6797\u7a33\u5b9a\u6027\u6709\u591a\u5dee\uff0c\u5355\u51ed\u5404\u79cd\u63d2\u4ef6\u826f\u83a0\u4e0d\u9f50\u7684\u4ee3\u7801\u8d28\u91cf\u6211\u5c31\u53d7\u4e0d\u4e86\u4e86\u3002\u53e6\u5916\uff0c\u9047\u5230\u95ee\u9898\u4e0d\u65b9\u4fbf\u8c03\u8bd5\u548c\u4fee\u590d\u4e5f\u662f\u6211\u653e\u5f03\u7684\u4e3b\u8981\u539f\u56e0\u3002 \u4e00\u4e0d\u505a\u4e8c\u4e0d\u4f11\uff0c4 \u6708 8 \u53f7\uff0cKexue Gateway \u7684\u524d\u8eab\u8bde\u751f\u4e86\uff0c\u5c31\u8fd9\u6837\u5f00\u542f\u4e86\u6f2b\u6f2b\u957f\u5f81\u8def\u3002\u8bb0\u5f97\u90a3\u65f6\u5019\u8fd8\u5728\u7528 Nano Pi\u3001\u6811\u8393\u6d3e\u4e4b\u7c7b\u7684 ARM \u4ea7\u54c1\uff0c\u6027\u80fd\u548c\u517c\u5bb9\u6027\u60e8\u4e0d\u5fcd\u7779\u3002 5 \u6708 8 \u53f7\uff0c\u6211\u51b3\u5b9a\u7f16\u6392\u4e00\u5957\u9002\u7528\u4e8e\u4efb\u4f55\u8def\u7531\u5668\uff08\u5728\u5c40\u57df\u7f51\u5185\u52a0\u5165\u4e00\u4e2a\u4e0d\u5e26 DHCP \u529f\u80fd\u7684\u989d\u5916\u7f51\u5173\uff09\uff0c\u4e14\u5c3d\u53ef\u80fd\u89c4\u8303\u3001\u539f\u751f\u3001\u53ef\u9760\u7684\u5f00\u6e90\u89e3\u51b3\u65b9\u6848\uff0c\u4e5f\u5c31\u662f\u73b0\u5728\u7684 Kexue Gateway \u9879\u76ee\u3002\u6b64\u540e\u76f4\u5230 7 \u6708\u5e95\uff0c\u6211\u5927\u90e8\u5206\u7684\u65f6\u95f4\u90fd\u94fa\u5728\u4e86\u8fd9\u4e2a\u9879\u76ee\u4e0a\uff0c\u4e0d\u65ad\u5730\u5b8c\u5584\u548c\u6539\u8fdb\u3002 6 \u6708 11 \u53f7\uff0c\u6ca1\u9519\uff0c\u6211\u5bf9\u5404\u8def\u673a\u573a\u4e5f\u5fcd\u65e0\u53ef\u5fcd\u4e86\u3002\u56e0\u4e3a\u516d\u6708\u521d\u56fd\u5185\u5bf9\u4e8e\u8fd9\u7c7b\u670d\u52a1\u7684\u7ba1\u5236\u592a\u4e25\u683c\uff0c\u5bfc\u81f4\u7a33\u5b9a\u6027\u5927\u4e0d\u5982\u4ece\u524d\uff1b\u53e6\u5916\u6574\u4e2a\u5708\u5b50\u662f\u975e\u592a\u591a\uff0c\u9664\u4e86\u7ecf\u5e38\u6709\u673a\u573a\u8dd1\u8def\u4e4b\u5916\uff0c\u8ba8\u8bba\u548c\u8bc4\u6d4b\u7684\u623e\u6c14\u4e5f\u90fd\u5f88\u91cd\u3002\u5b9e\u5728\u4e0d\u60f3\u6dcc\u8fd9\u6d51\u6c34\uff0c\u4e8e\u662f\u6211\u4e70\u4e86\u7b2c\u4e00\u53f0\u670d\u52a1\u5668\uff0c\u5e76\u5f00\u4e86\u4e00\u4e2a\u540d\u53eb Kexue Servers \u7684\u79c1\u6709\u4ed3\u5e93\uff0c\u7528\u6765\u7f16\u6392\u81ea\u5df1\u7684\u670d\u52a1\u3002\u5f53\u7136\uff0c\u6211\u4e0d\u613f\u6210\u4e3a\u81ea\u5df1\u8ba8\u538c\u7684\u4eba\uff0c\u6240\u4ee5\u4e00\u5f8b\u4e0d\u9500\u552e\u4e5f\u4e0d\u5206\u4eab\u3002 8 \u6708\u4efd\uff0c\u548c\u5de5\u4f5c\u65f6\u95f4\u7ebf\u4e00\u81f4\uff0c\u5bf9 Kubernetes \u548c Terraform \u7684\u70ed\u7231\u7206\u53d1\u4e86\u3002\u6211\u7528 Google Cloud Platform \u5269\u4f59\u7684\u8d60\u91d1\u5f00\u4e86 GKE \u96c6\u7fa4\uff0c\u987a\u4fbf\u8d2d\u4e70\u4e86\u51e0\u4e2a\u989d\u5916\u7684\u57df\u540d\uff0c\u5229\u7528 Terraform \u7ba1\u7406\u89e3\u6790\u8bb0\u5f55\uff1b\u51e1\u662f\u80fd\u8fc1\u79fb\u7684\u670d\u52a1\uff0c\u7edf\u7edf\u3001\u4e00\u5f8b\u642c\u4e0a Kubernetes\uff0c\u5305\u62ec\u4f60\u73b0\u5728\u770b\u5230\u7684 \u535a\u5ba2\uff08\u867d\u7136\u5b83\u73b0\u5728\u5df2\u7ecf\u88ab\u6211\u4e34\u65f6\u8fc1\u79fb\u56de\u865a\u62df\u673a\uff09\u3001\u5185\u7f51\u7a7f\u900f inlets\u3001Webhook \u8c03\u8bd5\u5de5\u5177 Webhook.site\u3001\u6587\u4ef6\u7ba1\u7406\u5668 KodExplorer \u7b49\u7b49\uff1b\u7ba1\u5b83\u6709\u6ca1\u6709\u7528\uff0c\u5148\u90e8\u7f72\u518d\u8bf4\u3002 \u5e74\u5e95\u4e4b\u524d\u4e00\u76f4\u5728\u7814\u7a76\u4ee3\u7406\u534f\u8bae\uff0c\u6ca1\u6709\u63a5\u89e6\u8fc7 VPN \u76f8\u5173\u7684\u6280\u672f\u3002\u60f3\u7740\u80fd\u591f\u6bd4\u56db\u5c42\u66f4\u52a0\u6df1\u5165\uff0c11 \u6708 10 \u53f7\uff0c\u6211\u5f00\u59cb\u5c1d\u8bd5\u80fd\u591f\u627f\u8f7d IP \u534f\u8bae\u3001\u751a\u81f3\u4e8c\u5c42\u534f\u8bae\u7684 VPN\u3002\u9762\u5bf9 IPSec\u3001WireGuard\uff0c\u90a3\u5c31\u4e0d\u5f97\u4e0d\u4e86\u89e3 Linux \u8def\u7531\u673a\u5236\uff0c\u76f4\u5230\u73b0\u5728\uff0c\u6211\u8fd8\u4e00\u76f4\u5728\u5b66\u4e60 Routing Table\uff0cBIRD \u7b49\u76f8\u5173\u77e5\u8bc6\u3002 12 \u6708\u5e95\uff0c\u4e5f\u5c31\u662f\u524d\u51e0\u5929\uff0c\u6211\u53c8\u628a\u535a\u5ba2\u91cd\u65b0\u6574\u7406\u4e86\u4e00\u4e0b\uff1b\u7b80\u5316\u6389\u4e0d\u5c11\u65e0\u7528\u7684\u52a8\u753b\u548c\u6837\u5f0f\uff0c\u8ba9\u8bfb\u8005\u548c\u6211\u7684\u4e13\u6ce8\u70b9\u66f4\u8d34\u8fd1\u5185\u5bb9\u3002\u5f88\u5de7\u7684\u662f\uff0c\u53bb\u5e74\u7684\u8fd9\u4e2a\u65f6\u5019\u6211\u4e5f\u5728\u4f18\u5316\u535a\u5ba2\u3002  \u5176\u5b9e\u6211\u662f\u4e2a\u5f88\u61d2\u7684\u4eba\uff0c\u5341\u5206\u5e86\u5e78\u5f53\u65f6\u5fcd\u53d7\u4e0d\u4e86\u7684\u65f6\u5019\uff0c\u9009\u62e9\u4e86\u81ea\u5df1\u52a8\u624b\u505a\u3002\u6211\u6ca1\u6709 CCIE\u3001JNCIE \u4e4b\u7c7b\u7684\u8bc1\u4e66\uff0c\u5b8c\u5168\u662f\u91ce\u8def\u5b50\u51fa\u8eab\uff0c\u4f46\u662f\u7ecf\u8fc7\u4e0d\u65ad\u7684\u5b66\u4e60\u548c\u5c1d\u8bd5\uff0c\u6700\u7ec8\u638c\u63e1\u4e86\u4e0d\u5c11\u300c\u6b63\u89c4\u300d\u7684\u7f51\u7edc\u77e5\u8bc6\u3002\u5e0c\u671b\u672a\u6765\u81ea\u5df1\u80fd\u591f\u4fdd\u6301\u8fd9\u6837\u5bf9\u672a\u77e5\u9886\u57df\u53d1\u8d77\u6311\u6218\u7684\u52c7\u6c14\u5427\u3002\n2019 \u603b\u7ed3 \u7ed3\u5408\u5de5\u4f5c\u548c\u4e2a\u4eba\u6210\u957f\u65f6\u95f4\u7ebf\uff0c\u6211\u57fa\u672c\u5f97\u51fa\u4eca\u5e74\u7684\u65f6\u95f4\u5206\u914d\u5360\u6bd4\uff1a\n\u79d1\u5b66\u4e0a\u7f51 4.5 : Kubernetes 2.5 : IT\/\u82f1\u8bed 1.5 : Terraform\/Prometheus 1 : PHP 0.5\n\u7a0d\u5fae\u51fa\u4e4e\u6211\u7684\u9884\u6599\uff0c\u79d1\u5b66\u4e0a\u7f51\u6240\u5360\u7684\u6bd4\u4f8b\u592a\u9ad8\u4e86\uff0c\u5e74\u521d\u7684\u9884\u671f\u5e94\u8be5\u662f\uff1a\n\u79d1\u5b66\u4e0a\u7f51 2 : Kubernetes 4 : \u82f1\u8bed 2 : Terraform\/Prometheus 1.5 : PHP 0.5\n2020 \u5c55\u671b \u6839\u636e\u6211\u81ea\u5df1\u7684\u804c\u4e1a\u89c4\u5212\u4ee5\u53ca\u5b9e\u9645\u60c5\u51b5\uff0c\u63a5\u4e0b\u6765\u4e00\u5e74\u7684\u76ee\u6807\u4e0e\u73b0\u6709\u65b9\u5411\u7c7b\u4f3c\uff1a\n \u4fdd\u8bc1\u8eab\u4f53\u5065\u5eb7\u3002 \u5feb\u901f\u5c06\u79d1\u5b66\u4e0a\u7f51\u76f8\u5173\u5185\u5bb9\u6536\u5c3e\uff0c\u8fdb\u5165\u7ef4\u62a4\u9636\u6bb5\uff0c\u4e0d\u518d\u5360\u7528\u5927\u91cf\u65f6\u95f4\u7ee7\u7eed\u5f00\u53d1\uff08\u5176\u5b9e 11 \u6708\u5c31\u6709\u8fd9\u4e2a\u60f3\u6cd5\uff0c\u5e0c\u671b\u5e74\u5e95\u80fd\u591f\u5c06\u8fd9\u65b9\u9762\u5b8c\u5168\u7ed3\u675f\uff0c\u53ea\u53ef\u60dc\u8ddd\u79bb\u6211\u7406\u60f3\u7684\u6c34\u51c6\u8fd8\u5dee\u70b9\u706b\u5019\uff09\u3002 \u6df1\u5165\u5b66\u4e60 Kubernetes\uff0c\u5305\u62ec\u76ee\u524d\u6682\u65f6\u4e0d\u719f\u6089\u7684\uff1a  Taint\u3001Tolerations\u3001Node Affinity\u3001Autoscaler\u3001Resource Request \u7b49\u7279\u6027\uff0c HorizontalPodAutoscaler\u3001PodSecurityPolicy\u3001NetworkPolicy\u3001LimitRange \u7b49\u8d44\u6e90\uff0c \u4ee5\u53ca\u4e89\u53d6\u80fd\u5bf9 CRI\/CSI\/CNI\u3001Scheduler \u7b49 Kubernetes \u5185\u90e8\u539f\u7406\u6709\u4e00\u5b9a\u4e86\u89e3\u3002   \u7ee7\u7eed\u953b\u70bc\u82f1\u8bed\uff0c\u5305\u62ec\uff1a  \u5c3d\u53ef\u80fd\u591a\u53c2\u4e0e\u90ae\u4ef6\u548c Slack \u8ba8\u8bba\uff0c \u575a\u6301\u7528\u82f1\u6587\u7f16\u5199\u6280\u672f\u5411\u535a\u6587\uff0c \u4ee5\u53ca\u4e89\u53d6\u7ec3\u4e60\u51e0\u6b21 italki\u3002   \u6df1\u5165\u5b66\u4e60 Prometheus\uff0c\u638c\u63e1\uff1a  PromQL \u8fdb\u9636\u8bed\u6cd5\uff0c \u901a\u8fc7 Prometheus Operator \u548c Custom Metrics \u5bf9 Kubernetes \u96c6\u7fa4\u76d1\u63a7\uff0c \u4ee5\u53ca\u63d0\u5347 Golang \u7f16\u7801\u6c34\u5e73\uff0c\u4e89\u53d6\u5199\u4e00\u4e2a Prometheus Exporter \u5e76\u5f00\u6e90\u3002    \u7406\u60f3\u5360\u6bd4\uff1a\nKubernetes 4 : \u82f1\u8bed 2 : Golang 1.5 : Prometheus 1 : \u79d1\u5b66\u4e0a\u7f51 1 : \u5176\u5b83 0.5\n\u660e\u5e74\u7684\u76ee\u6807\u76f8\u6bd4\u4eca\u5e74\u8be6\u7ec6\u4e86\u4e0d\u5c11\uff0c\u4efb\u91cd\u800c\u9053\u8fdc\u5440\u3002\n\u6700\u540e \u5176\u5b9e\u8fd9\u7bc7\u535a\u6587\u6700\u65e9\u7684\u6807\u9898\u662f\u300c\u4f60\u597d\uff0c2020\u300d\uff0c\u5728\u5199\u5230\u8fd9\u91cc\u7684\u65f6\u5019\uff0c\u6211\u51b3\u5b9a\u6539\u6210\u73b0\u5728\u7684\u6807\u9898\u3002\n\u5b9e\u5728\u6ca1\u60f3\u5230\u81ea\u5df1\u6587\u601d\u6cc9\u6d8c\u3002\n\u65b0\u5e74\u5feb\u4e50\u3002\n\ud83c\udf89\n","permalink":"https:\/\/wi1dcard.dev\/posts\/hello-2020\/","summary":"<p>\u8f6c\u773c\u95f4\u5230\u4e86 2019 \u5e74\u672b\uff0c\u8fd8\u8bb0\u5f97\u53bb\u5e74\u4e5f\u5199\u8fc7\u4e00\u7bc7\u7c7b\u4f3c\u7684 <a href=\"https:\/\/wi1dcard.dev\/posts\/hello-2019\/\" target=\"_blank\">\u535a\u5ba2<\/a>\uff1b\u8ba1\u5212\u4eca\u5e74\u7684\u300c\u5e74\u7ec8\u603b\u7ed3\u300d\u86ee\u4e45\u4e86\uff0c\u53ea\u662f\u89c9\u5f97\u65f6\u95f4\u8fd8\u65e9\u4fbf\u4e00\u76f4\u6ca1\u6709\u52a8\u624b\uff0c\u76f4\u5230\u4eca\u5929\u624d\u604d\u7136 \u2014\u2014 \u5df2\u7ecf\u662f 2019 \u5e74\u6700\u540e\u4e00\u5929\u4e86\u3002<\/p>","title":"\u4e00\u7bc7\u53c8\u957f\u53c8\u4e4f\u5473\u7684\u5e74\u7ec8\u603b\u7ed3\u548c\u5c55\u671b"},{"content":"After a few days working on Salesforce integration, I finnally finished a simple CLI edtion of DataLoader using prune TypeScript. Within lots of CSV rows loaded into memory, the node engine always crashs around 130k of records. In order to get this job done as quick as possible, I have to increase the max memory of Node.js.\nThe error message looks like:\nFATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory ... [1] 15759 abort node ... The quick but not perfect solution is:\nexport NODE_OPTIONS=&#34;--max_old_space_size=&lt;memory in MB&gt;&#34; Or,\nnode --max-old-space-size=&lt;memory in MB&gt; ... See also:\n https:\/\/futurestud.io\/tutorials\/node-js-increase-the-memory-limit-for-your-process ","permalink":"https:\/\/wi1dcard.dev\/posts\/increase-node-js-v8-memory-limit\/","summary":"<p>After a few days working on Salesforce integration, I finnally finished a simple CLI edtion of <a href=\"https:\/\/github.com\/forcedotcom\/dataloader\" target=\"_blank\">DataLoader<\/a> using prune TypeScript. Within lots of CSV rows loaded into memory, the node engine always crashs around 130k of records. In order to get this job done as quick as possible, I have to increase the max memory of Node.js.<\/p>","title":"Increase Node.js V8 Memory Limit"},{"content":"It&rsquo;s been a while maintaining the proxy services for my work friends who are in Beijing office. These days I tried to collect some basic metrics like online IP addresses and its connections. And I found a very simple way to do it with only netstat and several text process tools.\nFor instance, I would like to get the clients info connected to port 443:\nnetstat -ntu \\  # Collect network statistics and very detailed information | grep -v LISTEN \\  # Remove lines that the status is LISTEN | awk &#39;{print $4, $5}&#39; \\  # Remove other columns but retain the 4th and 5th ones | grep -E &#39;^[0-9\\.]+:443&#39; \\  # Filter connections to port 443 by a regex expression | cut -d&#39; &#39; -f2 \\  # Remove the first column which is server&#39;s address | cut -d: -f1 \\  # Strip the port part from IP addresses | sort \\  # Sort results for pipelining to uniq command | uniq -c # Group the IP addresses and calculate their appearing times (which is the number of connections) The final shell script looks like:\nnetstat -ntu | grep -v LISTEN | awk &#39;{print $4, $5}&#39; | grep -E &#39;^[0-9\\.]+:443&#39; | cut -d&#39; &#39; -f2 | cut -d: -f1 | sort | uniq -c And also the results:\n 8 180.xx.xx.74 1 183.xx.xx.53 12 218.xx.xx.198 20 221.xx.xx.37 32 222.xx.xx.252 ","permalink":"https:\/\/wi1dcard.dev\/posts\/list-connections-group-by-ip\/","summary":"<p>It&rsquo;s been a while maintaining the proxy services for my work friends who are in Beijing office. These days I tried to collect some basic metrics like online IP addresses and its connections. And I found a very simple way to do it with only <code>netstat<\/code> and several text process tools.<\/p>","title":"List All IP Addresses and the Number of Connections to a Port"},{"content":"OpenDNS has a &ldquo;un-official&rdquo; (I didn&rsquo;t find any docs at least) API for returning your public IP, by a normal DNS query.\ndig @resolver1.opendns.com -t A -4 myip.opendns.com +short ","permalink":"https:\/\/wi1dcard.dev\/posts\/find-your-public-ip-via-dns-protocol\/","summary":"<p>OpenDNS has a &ldquo;un-official&rdquo; (I didn&rsquo;t find any docs at least) API for returning your public IP, by a normal DNS query.<\/p>","title":"Find Your Public IP Address via DNS Protocol"},{"content":"Recently, I&rsquo;ve been working against Kubernetes and Helm for a while. Today, I faced a strange problem that could only be triggered in a very very specific condition. After determined what happened under the hood, I decided to write it down in case someone else needs it.\n Also, BTW, to practice my English. :D\n Let&rsquo;s say we have a retail-api chart that contains some normal services and deployments like others do. And mysql chart is one of the dependencies of it.\nAlso, we set up GitLab CI review apps to install and upgrade the chart using helmfile. That means every new branch creates a fresh environment, including the release and its resources. Actually, we are now starting to work with review apps recently. So we choose to use $CI_COMMIT_REF_SLUG for the environment url, also a part of the Helm release name as the doc says.\nIn the first few days, it works perfectly as expected, until I pushed a branch named bugfix\/hook-deploy-mysql-connection-timeout:\n$ helmfile -e ${HELM_ENVIRONMENT} apply --suppress-secrets --concurrency=1 ... Comparing release=retail-api-bugfix-hook-deploy-mysql-connection-timeout, chart=deploy\/chart in .\/helmfile.yaml: failed processing release retail-api-bugfix-hook-deploy-mysql-connection-timeout: helm exited with status 1: Error: invalid release name, must match regex ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+$ and the length must not be longer than 53 Error: plugin &quot;diff&quot; exited with error \/root\/.helm\/plugins\/helm-tiller\/scripts\/tiller.sh: line 174: 144 Killed .\/bin\/tiller --storage=${HELM_TILLER_STORAGE} --listen=127.0.0.1:${HELM_TILLER_PORT} ${PROBE_LISTEN_FLAG} --history-max=${HELM_TILLER_HISTORY_MAX} (wd: ~\/.helm\/plugins\/helm-tiller) Error: plugin &quot;tiller&quot; exited with error Looks like easy to fix. I edit the helmfile.yaml then, using functions trunc and trimSuffix to build a vaild release name:\nreleases: - name: retail-api-{{ requiredEnv &#34;CI_COMMIT_REF_SLUG&#34; | trunc 32 | trimSuffix &#34;-&#34; }} After so, the release name has been truncated to retail-api-bugfix-hook-deploy-mysql-connect. Things weird started from now on, see the CI logs:\nUpgrading release=retail-api-bugfix-hook-deploy-mysql-connect, chart=deploy\/chart Creating tiller namespace (if missing): tiller Release &quot;retail-api-bugfix-hook-deploy-mysql-connect&quot; does not exist. Installing it now. in .\/helmfile.yaml: failed processing release retail-api-bugfix-hook-deploy-mysql-connect: helm exited with status 1: Error: release retail-api-bugfix-hook-deploy-mysql-connect failed: services &quot;retail-api-bugfix-hook-deploy-mysql-connect&quot; already exists Error: plugin &quot;tiller&quot; exited with error ERROR: Job failed: command terminated with exit code 1 The previous failed job mistakenly leads me to the wrong hypothesis - it is due to the length. In order to verify, I even tried to shorten the release name by decrease 32 characters into 16:\nreleases: - name: retail-api-{{ requiredEnv &#34;CI_COMMIT_REF_SLUG&#34; | trunc 16 | trimSuffix &#34;-&#34; }} It is now retail-api-bugfix-hook-depl, and works well.\nSo, I put all my minds to the length issue, and did the following research:\n The logs said that a service already exists. Is there any additional limitation for services in Kubernetes? Refer to the naming doc, No. Do the DNS specs or other RFCs ever specify the max length? Yes, but 63 characters. Even the longer service name is just 43 chars. Fair enough to the requirements. Okay, no reference pointing to this issue. Let&rsquo;s have a diagnosis of exclusion. First, I found all usages of the release name is only the retail.fullname helper function, which is generated by Helm by default. Fix the helper, fix the problem. Then I tried to truncate every value of fields that contains {{ include &quot;retail.fullname&quot; . }}, one by one. Finally, I located 2 resources - the deployment and service, both of them use exact the helper as their name. In order to find the critical value that can precisely reproduce this issue, I started to try it from {{ include &quot;retail.fullname&quot; . | trunc 20 }} to {{ include &quot;retail.fullname&quot; . | trunc 43 }}. I got every test passed, except for 43, which is the original full name without being cut out.  After that, I started to think, do we really have any &ldquo;dirty&rdquo; resource being conflicted? It seems not. But checking out successful applied releases makes me have some new discoveries. The release actually deployed 2 deployment and services that have similar names:\n==&gt; v1\/Deployment NAME READY UP-TO-DATE AVAILABLE AGE retail-api-bugfix-hook-deploy-mysql-connec 0\/1 1 0 5s ==&gt; v1beta1\/Deployment NAME READY UP-TO-DATE AVAILABLE AGE retail-api-bugfix-hook-deploy-mysql-connect 0\/1 1 0 5s ==&gt; v1\/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE retail-api-bugfix-hook-deploy-mysql-connect ClusterIP 10.100.57.38 &lt;none&gt; 3306\/TCP 6s retail-api-bugfix-hook-deploy-mysql-connec ClusterIP 10.100.192.93 &lt;none&gt; 80\/TCP 6s That is very confusing. Did I just catch a bug in Helm?\nObviously, not. Suddenly, I saw an abnormal value of the service:\n$ kubectl get service -n review-apps NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE retail-api-bugfix-hook-deploy-mysql-connect ClusterIP 10.100.57.38 &lt;none&gt; 3306\/TCP 18h Port 3306? That&rsquo;s the service of mysql chart, not ours! Finally, I realized that is because the mysql.fullname helper generates the same value of retail.fullname does, due to the if statement in the helper:\n{{- $name := default .Chart.Name .Values.nameOverride -}} {{- if contains $name .Release.Name -}} {{- printf .Release.Name | trunc 63 | trimSuffix &quot;-&quot; -}} The name of the mysql service and deployment will be exactly the release name if it contains mysql, the chart name.\nIn the end, I haven&rsquo;t been digging deeper for the reason why the developers of helm would like to do it that way. In fact, I don&rsquo;t really like that kind of behavior, which does not &ldquo;show up&rdquo; in my daily ops. Even though I might read the codes someday, it could be easily forgotten.\nHowever, this time of debugging notices me it&rsquo;s worth to pay more attention while we are using helpers and building resource names, and be careful using some kind of &ldquo;user-generated&rdquo; value as a Helm release name.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/helm-template-resource-already-exists\/","summary":"<p>Recently, I&rsquo;ve been working against Kubernetes and Helm for a while. Today, I faced a strange problem that could only be triggered in a very very specific condition. After determined what happened under the hood, I decided to write it down in case someone else needs it.<\/p>\n<blockquote>\n<p>Also, BTW, to practice my English. :D<\/p>\n<\/blockquote>","title":"Helm Chart Resource Names Conflict Due to the Fullname Helper"},{"content":"\uff08\u63a5\u4e0a\u6587\uff09\n\u524d\u9762\u7684\u90e8\u5206\u4ecb\u7ecd\u4e86\u5982\u4f55\u4e3a\u6211\u7684\u535a\u5ba2\u6253\u5305 Docker \u955c\u50cf\uff0c\u63a5\u4e0b\u6765\u5c31\u662f\u91cd\u5934\u620f \u2014\u2014 \u90e8\u7f72\u5230 Kubernetes\u3002\nGoogle Kubernetes Engine \u6ca1\u9519\uff0c\u6211\u73b0\u5728\u81ea\u7528\u7684 Kubernetes \u96c6\u7fa4\u5c31\u662f Google \u5bb6\u7684 GKE\u3002\u6682\u65f6\u6ca1\u6709\u9047\u5230\u4ec0\u4e48\u592a\u5927\u7684\u5751\uff0c\u5404\u65b9\u9762\u96c6\u6210\u505a\u5f97\u4e0d\u9519\uff0c\u9002\u5408\u6211\u8fd9\u79cd\u5c0f\u767d\u4e0a\u624b\u3002\nHelm \u6709 Kubernetes \u5f53\u7136\u5c11\u4e0d\u4e86 Helm\u3002\u5728\u6211\u7684\u7406\u89e3\u4e2d\uff0cHelm \u9664\u4e86\u662f\u4e00\u4e2a\u6a21\u677f\u5f15\u64ce\u4e4b\u5916\uff0c\u8fd8\u80fd\u628a\u4e00\u6574\u4e2a\u300c\u5e94\u7528\u300d\u6240\u9700\u8981\u7684 YAML \u6587\u4ef6\u7ec4\u5408\u4e3a\u4e00\u4e2a\u6574\u4f53\uff08Chart\uff09\uff0c\u591a\u4e2a Chart \u4e4b\u95f4\u53ef\u4ee5\u4e92\u76f8\u4f9d\u8d56\uff0c\u7ec4\u5408\u6210\u4e3a\u4e00\u6574\u4e2a\u7cfb\u7edf\uff1b\u642d\u914d helm-diff\uff0chelm-secret \u7b49\u63d2\u4ef6\u8fd8\u53ef\u4ee5\u5c55\u793a YAML \u6587\u4ef6\u53d8\u66f4\u3001\u7ba1\u7406\u654f\u611f\u5bc6\u94a5\u4fe1\u606f\u7b49\u3002\n\u9996\u5148\uff0c\u6211\u4f7f\u7528 helm create \u521b\u5efa\u4e86\u4e00\u4e2a Chart\uff0c\u5e76\u5c06\u5b83\u76f4\u63a5\u653e\u5728\u4e86 deploy\/chart \u76ee\u5f55\u3002\n\u9ed8\u8ba4 Chart \u5185\u7684 YAML \u6a21\u677f\u57fa\u672c\u6ca1\u6709\u4fee\u6539\uff0c\u53ea\u6709 values.yaml \u6539\u4e86\u4e00\u4e9b\u503c\uff1a\nimage: repository: wi1dcard\/blog \u6b63\u5982\u4f60\u770b\u5230\u7684\uff0c\u955c\u50cf\u88ab\u4fee\u6539\u6210\u4e86 wi1dcard\/blog\uff08\u4e0a\u6587\u4e2d\u63a8\u9001\u5230 Docker Hub \u7684\u955c\u50cf\uff09\u3002\u540c\u65f6\uff0c\u6211\u542f\u7528\u4e86 Ingress\uff0c\u8fd8\u7ed9 Ingress \u6dfb\u52a0\u4e86\u4e00\u4e9b\u6ce8\u89e3\uff1a\ningress: enabled: true annotations: kubernetes.io\/tls-acme: &#34;true&#34; ingress.kubernetes.io\/ssl-redirect: &#34;true&#34; ingress.kubernetes.io\/browser-xss-filter: &#34;true&#34; # X-XSS-Protection: 1; mode=block ingress.kubernetes.io\/content-type-nosniff: &#34;true&#34; # X-Content-Type-Options: nosniff ingress.kubernetes.io\/referrer-policy: strict-origin-when-cross-origin # Referrer-Policy: same-origin ingress.kubernetes.io\/custom-frame-options-value: SAMEORIGIN # X-Frame-Options: SAMEORIGIN ingress.kubernetes.io\/custom-response-headers: X-Powered-By:Wi1dcard Kubernetes Engine \u6211\u4f7f\u7528\u7684\u662f Traefik Ingress Controller\uff0c\u76f8\u6bd4\u4e8e Nginx Ingress Controller \u7ed9 Nginx \u52a0\u4e2a\u4e2d\u95f4\u5c42\u6765\u8bf4\uff0cTraefik \u672c\u8eab\u65e2\u662f Ingress Controller \u53c8\u662f Ingress \u7684\u5177\u4f53\u5b9e\u73b0\uff1b\u800c\u4e14\u6211\u6ca1\u6709\u56db\u5c42\u534f\u8bae\u7684\u9700\u6c42\uff0c\u6027\u80fd\u66f4\u662f\u5b8c\u5168\u65e0\u6240\u8c13\uff08\u5f53\u7136 Traefik \u4e0d\u4e00\u5b9a\u6bd4 Nginx \u5dee\uff09\uff0c\u6240\u4ee5\u76f4\u63a5\u9009\u62e9\u4e86\u4e3a\u300c\u4e91\u539f\u751f\u300d\u8bbe\u8ba1\u7684 Traefik\u3002\n\u8fd9\u4e9b Annotations \u591a\u6570\u90fd\u662f\u6211\u4ece Traefik Kubernetes Ingress Docs \u6284\u8fc7\u6765\u7684\ud83d\ude02\uff0c\u9664\u4e86\u5f3a\u5236\u8df3\u8f6c HTTPS \u4e4b\u5916\uff0c\u5b83\u4eec\u8fd8\u53ef\u4ee5\u8ba9 Traefik Ingress \u8fd4\u56de\u7684 HTTP \u54cd\u5e94\u5305\u542b\u7279\u5b9a\u7684\u300c\u5b89\u5168\u5934\u4fe1\u606f\uff08Security Headers\uff09\u300d\uff0c\u5bf9\u9650\u5236\u6d4f\u89c8\u5668\u6743\u9650\u3001\u4fdd\u969c\u7528\u6237\u6d4f\u89c8\u7ad9\u70b9\u65f6\u7684\u5b89\u5168\u6027\u6709\u4e00\u5b9a\u4f5c\u7528\u3002\n \u66f4\u591a\u6709\u5173 Security Headers \u7684\u8bf4\u660e\uff0c\u53ef\u4ee5\u53c2\u8003 https:\/\/securityheaders.com\/\u3002\n \u53e6\u5916\uff0c\u503c\u5f97\u6ce8\u610f\u7684\u662f kubernetes.io\/tls-acme: &quot;true&quot;\uff0c\u8fd9\u6761\u6ce8\u89e3\u662f\u4e3a\u4e86\u914d\u7f6e\u81ea\u52a8\u7533\u8bf7\u8bc1\u4e66\u4f7f\u7528\uff0c\u6211\u4f7f\u7528\u7684\u662f cert-manager\uff0c\u5b83\u80fd\u591f\u5e2e\u6211\u89e3\u51b3\u300c\u8001\u5927\u96be\u300d\u7684 Let&rsquo;s Encrypt \u8bc1\u4e66\u7533\u8bf7\u3001\u7eed\u671f\u95ee\u9898\u3002\u5728\u6b64\u4e0d\u518d\u5c55\u5f00\uff0c\u5f85\u6709\u7a7a\u65f6\u53e6\u5f00\u535a\u5ba2\u8be6\u7ec6\u8bf4\u660e\u3002\nHelmfile \u4e0d\u5c11\u4eba\u8bf4 Helm \u7528\u4e8e\u7ba1\u7406 Kubernetes \u7684 YAML\uff0c\u800c Helmfile \u5c31\u662f\u7528\u6765\u7ba1\u7406 Helm \u7684 Helm&hellip; \ud83d\ude02\n\u7b97\u662f\u4e2a\u6bd4\u8f83\u5f62\u8c61\uff0c\u5e26\u6709\u73a9\u7b11\u6210\u5206\u7684\u6bd4\u55bb\u5427\u3002Helmfile \u7684\u529f\u80fd\u5f88\u591a\uff0c\u4ee5\u6211\u73b0\u5728\u7684\u77e5\u8bc6\u91cf\u65e0\u6cd5\u4e00\u4e00\u5217\u51fa\uff1b\u81f3\u5c11\u5728\u90e8\u7f72\u6211\u7684\u535a\u5ba2\u7684\u8fc7\u7a0b\u4e2d\uff0c\u5b83\u53ef\u4ee5\u63d0\u4f9b\u4ee5\u4e0b\u5e2e\u52a9\uff1a\n Helm v2 Tillerless\uff08\u6b64\u5904\u6ce8\u660e\u7248\u672c\u662f\u56e0\u4e3a Helm v3 \u5df2\u7ecf\u8fdb\u5165 Alpha \u9636\u6bb5\uff0c\u5347\u7ea7\u540e\u5b8c\u5168\u53d6\u6d88 Tiller \u6982\u5ff5\uff0c\u56e0\u6b64 Tillerless \u6682\u4e0d\u8be6\u8ff0\uff0c\u6709\u5174\u8da3\u53ef\u81ea\u884c Google \u4e86\u89e3\uff09\u3002 \u8f93\u51fa YAML \u6587\u4ef6\u53d8\u66f4\uff08\u901a\u8fc7 helm-diff \u63d2\u4ef6\uff09\u3002 \u7ba1\u7406 Helm Chart \u4ed3\u5e93\uff0c\u81ea\u52a8\u4fdd\u6301\u66f4\u65b0\u3002 \u6700\u91cd\u8981\u7684\u4e00\u70b9 \u2014\u2014 \u901a\u8fc7\u73af\u5883\u53d8\u91cf\u8986\u76d6\u7279\u5b9a Values \u7684\u503c\u3002  \u5728 helmfile.yaml \u5185\u53ef\u4ee5\u67e5\u770b\u5230\u6211\u7684 Helmfile \u914d\u7f6e\uff0c\u6700\u4e3b\u8981\u7684\u90e8\u5206\u5c31\u662f releases \u5c0f\u8282\uff1a\nreleases: - name: blog # Helm Release \u540d\u79f0 namespace: blog # \u90e8\u7f72\u5230\u7684 Kubernetes \u547d\u540d\u7a7a\u95f4 chart: .\/chart # Helm Chart \u7684\u540d\u79f0\u6216\u672c\u5730\u8def\u5f84 values: # \u8986\u76d6 Chart \u7684\u9ed8\u8ba4 Values - image: tag: {{ requiredEnv &#34;DOCKER_TAG&#34; }} ingress: hosts: - host: {{ requiredEnv &#34;INGRESS_HOST&#34; }} paths: [ \/ ] - host: wi1dcard.dev paths: [ \/ ] tls: - secretName: ingress-tls hosts: [ {{ requiredEnv &#34;INGRESS_HOST&#34; }} ] \u4e0e Helm \u7c7b\u4f3c\uff0cHelmfile \u4f1a\u5c06 helmfile.yaml \u4f5c\u4e3a Go Template \u6e32\u67d3\u3002\u5982\u4f60\u6240\u89c1\uff0c\u5728\u4ee5\u4e0a\u7247\u6bb5\u4e2d\uff0c\u6211\u4f7f\u7528\u4e86 {% raw %}{{ ... }}{% endraw %} \u8bed\u6cd5\u548c requiredEnv \u51fd\u6570\u3002\nrequiredEnv \u662f Helmfile \u63d0\u4f9b\u7684\u529f\u80fd\u4e4b\u4e00\uff0c\u80fd\u591f\u83b7\u53d6\u6307\u5b9a\u73af\u5883\u53d8\u91cf\u7684\u503c\uff0c\u5e76\u53c2\u4e0e\u6a21\u677f\u6e32\u67d3\uff1b\u4f8b\u5982 {% raw %}{{ requiredEnv &quot;INGRESS_HOST&quot; }}{% endraw %} \u5373\u4e3a\u8bfb\u53d6 INGRESS_HOST \u53d8\u91cf\u3002\n\u914d\u5408\u8986\u76d6 Chart \u9ed8\u8ba4\u7684 Values\uff0c\u4fbf\u80fd\u591f\u5b9e\u73b0\u4e0a\u6587\u4e2d\u63d0\u5230\u7684\u7b2c\u300c4\u300d\u70b9\u3002\n\u6301\u7eed\u4ea4\u4ed8\uff08CD\uff09 \u8fd9\u6837\u4e00\u6765\uff0c\u501f\u52a9\u4e8e Helmfile\uff0c\u6211\u53ef\u4ee5\u5728 CI\/CD \u8fc7\u7a0b\u4e2d\u7075\u6d3b\u5730\u63a7\u5236\u90e8\u7f72\u7684\u955c\u50cf\uff08$DOCKER_TAG\uff09\u3001\u9690\u85cf CDN \u80cc\u540e\u7684\u88f8\u57df\u540d\uff08$INGRESS_HOST\uff09&hellip;\n\u6700\u540e\u4e00\u6b65\uff0cCD\u3002\u5728 deploy\/deploy.sh \u4e2d\uff0c\u6211\u4f7f\u7528\u4e86 Helmfile \u7684\u5b98\u65b9\u955c\u50cf\uff1a\necho &#34;Applying helm releases...&#34; docker run --rm -v &#34;$PWD\/deploy:\/deploy&#34; \\  -e HELM_TILLER_STORAGE=configmap \\  -e KUBECONFIG_BASE64=&#34;$KUBECONFIG_BASE64&#34; \\  -e DOCKER_TAG=&#34;$DOCKER_TAG&#34; \\  -e INGRESS_HOST=&#34;$INGRESS_HOST&#34; \\  quay.io\/roboll\/helmfile:v0.82.0 \/deploy\/helmfile.sh  \u8fd9\u4e0d\u662f\u89c4\u8303\u7684\u505a\u6cd5\uff01\u82e5\u662f\u540e\u671f\u8fc1\u79fb\u5230\u7c7b\u4f3c GitLab CI \u7b49 Dockerized CI\uff0c\u90a3\u4e48\u53ea\u9700\u8981\u58f0\u660e\u53e6\u4e00\u4e2a Job \u5373\u53ef\uff0c\u800c\u4e0d\u5fc5\u81ea\u884c\u542f\u52a8\u5bb9\u5668\u3002\n \u5728\u5bb9\u5668\u5185\uff0c\u6211\u4f7f\u7528\u4e86 deploy\/helmfile.sh \u811a\u672c\uff1b\u5b83\u9664\u4e86\u5e2e\u6211\u89e3\u7801 $KUBECONFIG_BASE64 \u5e76\u586b\u5230 ~\/.kube\/config \u4e4b\u5916\uff0c\u53ea\u6709\u4e24\u6761\u547d\u4ee4\u4e0e\u771f\u6b63\u610f\u4e49\u4e0a\u7684\u300c\u90e8\u7f72\u300d\u6709\u5173\uff1a\n# \u521d\u59cb\u5316 Helm\uff0c\u4f46\u4e0d\u5b89\u88c5 Tiller\u3002 helm init --client-only # \u90e8\u7f72\u3002 helmfile -f deploy\/helmfile.yaml apply --suppress-secrets \u6ca1\u9519\uff0c\u5230\u6700\u540e\u90e8\u7f72\u53ea\u5269\u4e0b\u4e00\u884c\u547d\u4ee4\u3002\u5176\u4e2d\uff1a\n -f deploy\/helmfile.yaml \u7528\u4e8e\u6307\u5b9a helmfile.yaml \u7684\u8def\u5f84\u3002 apply \u662f Helmfile \u7684\u5b50\u547d\u4ee4\uff0c\u76f4\u8bd1\u4e3a\u300c\u5e94\u7528\u300d\uff0c\u4f60\u53ef\u4ee5\u7406\u89e3\u4e3a\u300c\u90e8\u7f72\u300d\u3002 --suppress-secrets \u8868\u793a\u9690\u85cf Secrets\uff0c\u907f\u514d\u5bc6\u94a5\u5185\u5bb9\u88ab\u76f4\u63a5\u8f93\u51fa\u5230 CI \u65e5\u5fd7\u4e2d\u3002  \u6700\u7ec8\u6548\u679c \u5269\u4e0b\u7684\u90fd\u4ea4\u7ed9 Helmfile\u3001Helm\u3001Kubernetes \u5c31\u597d\u3002\u5b83\u4eec\u7d27\u5bc6\u534f\u4f5c\uff0c\u6839\u636e\u4f60\u7684\u914d\u7f6e\uff0c\u6700\u7ec8\u5c06\u5e94\u7528\u90e8\u7f72\u5230\u96c6\u7fa4\u4e2d\uff1a\n$ kubectl get pods -n blog NAME READY STATUS RESTARTS AGE blog-74d758cb84-w5z9k 1\/1 Running 0 21h \u4f60\u53ef\u4ee5\u5728 \u8fd9\u91cc \u67e5\u770b\u5b8c\u6574\u7684\u6784\u5efa\u548c\u90e8\u7f72\u65e5\u5fd7\uff0c\u4ee5\u53ca \u5386\u53f2\u3002\n\u4ee5\u53ca\u6211\u7684\u535a\u5ba2\uff1a\n$ curl -I https:\/\/wi1dcard.dev\/ HTTP\/2 200 date: Thu, 12 Sep 2019 13:05:37 GMT content-type: text\/html ... x-powered-by: Wi1dcard Kubernetes Engine \ud83d\ude04\n\u7ed3\u8bed \u9996\u5148\u611f\u8c22 Xiangxuan Liu\uff08@nauxliu\uff09\u5728\u6211\u5b66\u4e60 Kubernetes \u8fc7\u7a0b\u4e2d\u7684\u5e2e\u52a9\u548c\u6307\u5bfc\uff0c\u8282\u7701\u4e86\u5927\u91cf\u8bd5\u9519\u6210\u672c\uff0c\u5c11\u7ed5\u4e86\u5f88\u591a\u5f2f\u8def\uff0c\u7b97\u5f97\u4e0a\u662f\u53d7\u76ca\u532a\u6d45\u5427\u3002\u5728\u516c\u53f8\u4e0d\u597d\u610f\u601d\u8bf4\uff0c\u5c31\u8fd8\u662f\u5199\u5728\u535a\u5ba2\u91cc\u5427&hellip; \u54b3\u54b3\u3002\u6587\u4e2d\u6d89\u53ca\u7684\u6280\u672f\u6808\u5747\u53d6\u81ea\uff08\u6216\u884d\u751f\u81ea\uff09\u6211\u53f8\u73b0\u6709\u7684 Kubernetes \u76f8\u5173\u6280\u672f\uff0c\u611f\u5174\u8da3\u7684\u8bdd\uff0c\u7b80\u5386\u4e22\u6765\u5427\uff1ahttps:\/\/join.rightcapital.com\/\uff08\u867d\u7136\u6682\u65f6\u4e0d\u62db DevOps \ud83d\ude02\uff0c\u4e0d\u8fc7\u524d\u540e\u7aef\u90fd\u5728\u62db\u5440\uff09\u3002\n\u6700\u540e\uff0cKubernetes \u662f\u4e2a\u975e\u5e38\u7e41\u590d\u7cbe\u7f8e\u7684\u9879\u76ee\uff0c\u6211\u6700\u8fd1\u521a\u521a\u5165\u95e8\uff1b\u672c\u6587\u7684\u76ee\u7684\u5e76\u4e0d\u662f\u4e3a\u5927\u5bb6\u63d0\u4f9b\u8be6\u5c3d\u7684\u53c2\u8003\uff0c\u800c\u662f\u5728\u6211\u6f2b\u6f2b\u5b66\u4e60\u957f\u8def\u4e2d\u7684\u4e00\u4e9b\u968f\u7b14\u8bb0\u5f55\u5427\u3002\n\u5f53\u7136\uff0c\u65b0\u624b \u2260 \u4e0d\u8ffd\u6c42\u4e13\u4e1a\uff0c\u5982\u6587\u4e2d\u6709\u4efb\u4f55\u9519\u8bef\u656c\u8bf7\u6307\u51fa\uff0c\u6211\u4f1a\u5c3d\u5feb\u4fee\u6539\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/migrate-to-kubernetes-ii\/","summary":"<p>\uff08\u63a5\u4e0a\u6587\uff09<\/p>\n<p>\u524d\u9762\u7684\u90e8\u5206\u4ecb\u7ecd\u4e86\u5982\u4f55\u4e3a\u6211\u7684\u535a\u5ba2\u6253\u5305 Docker \u955c\u50cf\uff0c\u63a5\u4e0b\u6765\u5c31\u662f\u91cd\u5934\u620f \u2014\u2014 \u90e8\u7f72\u5230 Kubernetes\u3002<\/p>","title":"\u6211\u5982\u4f55\u5c06\u535a\u5ba2\u8fc1\u79fb\u5230 Kubernetes - II"},{"content":"\u6700\u8fd1 Kubernetes \u7684\u53d1\u5c55\uff0c\u4ee5\u53ca\u5728\u6211\u53f8\u7684\u5927\u91cf\u5e94\u7528\uff0c\u81ea\u5df1\u4e5f\u8feb\u4e0d\u53ca\u5f85\u60f3\u8981\u5c1d\u5c1d\u9c9c\uff0c\u867d\u7136\u6211\u7684\u535a\u5ba2\u662f\u57fa\u4e8e Hexo \u7684\u7eaf\u9759\u6001\u7ad9\u70b9\uff0c\u4f46\u8fd9\u5e76\u4e0d\u80fd\u963b\u6321\u6211\u628a\u5b83\u8fc1\u79fb\u4e0a Kubernetes\uff01\u6bd5\u7adf&hellip; \u76f8\u6bd4\u4e8e GitHub Pages \u7075\u6d3b\u6027\u66f4\u597d\u53ef\u63a7\u6027\u66f4\u9ad8\uff0cemmmm&hellip; \u597d\u4e86\u6211\u7f16\u4e0d\u4e0b\u53bb\u4e86\uff0c\u603b\u4e4b\uff0c\u751f\u547d\u5728\u4e8e\u6298\u817e\ud83d\ude02\uff0c\u6211\u4eec\u5f00\u59cb\u5427\u3002\n \u672c\u6587\u6d89\u53ca\u7684\u4ee3\u7801\uff08\u4e5f\u5c31\u662f\u6211\u7684\u535a\u5ba2\uff09\u5b8c\u5168\u5f00\u6e90\uff1ahttps:\/\/github.com\/wi1dcard\/blog\u3002\n \u6784\u5efa Docker \u955c\u50cf \u8981\u4e0a Kubernetes\uff0c\u9996\u5148\u8981\u505a\u7684\u5c31\u662f\u7ed9\u9879\u76ee\u6253\u5305\u955c\u50cf\u3002Dockerfile \u975e\u5e38\u7b80\u5355\uff1a\n# \u91c7\u7528 nginx:stable-alpine \u4f5c\u4e3a\u57fa\u7840\u955c\u50cfFROMnginx:stable-alpine# \u590d\u5236 .\/public \u5230\u955c\u50cf\u5185 \/usr\/share\/nginx\/htmlCOPY .\/public \/usr\/share\/nginx\/html# \u63d0\u793a\u66b4\u9732 TCP \u534f\u8bae 80 \u7aef\u53e3EXPOSE80\/tcp\u6211\u9009\u7528 Docker Hub \u4f5c\u4e3a Docker Registry\uff0c\u5982\u679c\u4f60\u6709\u79c1\u6709\u9879\u76ee\u3001\u6743\u9650\u63a7\u5236\u7b49\u76f8\u5173\u9700\u6c42\uff0cQuay.io \u6216\u8bb8\u662f\u66f4\u597d\u7684\u9009\u62e9\u3002\nCI \u6784\u5efa \u5f53\u7136\u5566\uff0c\u6784\u5efa\u8fd9\u79cd\u4e8b\u60c5\u80af\u5b9a\u662f\u4ea4\u7ed9 CI\u3002\u4e0d\u63a8\u8350\u6bcf\u6b21\u53d8\u66f4\u624b\u52a8 Build\uff0c\u8d39\u65f6\u8d39\u529b\u6613\u51fa\u9519\u3002\n\u76ee\u524d\u6211\u7ed9\u535a\u5ba2\u7528\u7684\u662f Travis CI\u3002\u6211\u4e5f\u8003\u8651\u8fc7\uff1a\n Circle CI\uff0c\u8bd5\u7528\u540e\u611f\u89c9\u914d\u7f6e\u6587\u4ef6\uff08\u4ee5\u6211\u4e2a\u4eba\u7684\u98ce\u683c\u6765\u770b\uff09\u6709\u70b9\u53cd\u76f4\u89c9\uff0c\u653e\u5f03\u3002 GitLab CI\uff0c\u76ee\u524d\u6211\u8ba4\u4e3a\u6700\u597d\u7684 CI\/CD\uff0c\u6211\u5177\u5907 CI\/CD \u9700\u6c42\u7684\u79c1\u4eba\u9879\u76ee\u90fd\u5728 GitLab\u3002\u4f46\u662f\u8003\u8651\u5230 (1) \u8981\u5c06\u535a\u5ba2\u4ee3\u7801\u5f00\u6e90\uff0c(2) GitLab CI for GitHub repos \u9700\u8981\u4ed8\u8d39\uff0c(3) \u4e24\u5957 VCS \u611f\u89c9\u602a\u602a\u7684\uff0c\u56e0\u6b64\u653e\u5f03\u3002 GitHub Actions\uff0c\u6b63\u5728 Beta \u4e2d\uff0c\u6253\u8d25\u5404\u8def CI\/CD \u7684\u79cd\u5b50\u9009\u624b\u4e4b\u4e00\u3002\u53ea\u53ef\u60dc\u6587\u6863\u8fd8\u4e0d\u591f\u9f50\u5168\uff0c\u7a33\u5b9a\u6b20\u4f73\uff0c\u53ea\u597d\u6682\u65f6\u653e\u5f03\u3002 Docker Hub\uff0c\u82e5\u662f\u53ea\u7528\u6765\u6784\u5efa\u516c\u5f00\u955c\u50cf\u611f\u89c9\u8fd8\u4e0d\u9519\uff0c\u4f46 (1) CI \u548c Docker Registry \u5f3a\u7ed1\u5b9a\uff0c\u60f3\u8981\u6362 Registry\uff08\u6bd4\u5982\u4e0a\u6587\u4e2d\u63d0\u5230\u7684 Quay.io\uff09\u4f1a\u5f88\u7e41\u7410\uff0c(2) \u6784\u5efa\u901f\u5ea6\u5de8\u6162&hellip; \u6162&hellip; \u6162&hellip; \u5927\u6982\u662f\u7528\u6237\u592a\u591a\u5427\uff0c\u60c5\u6709\u53ef\u539f\uff0c(3) \u955c\u50cf\u6253\u5305\u5b8c\u6210\u540e\u9700\u8981\u4f7f\u7528 Helm \u90e8\u7f72\uff08\u5373 CD\uff09\u5230\u96c6\u7fa4\uff0c\u660e\u663e\u4e0d\u9002\u5408\u8be5\u573a\u666f\u3002  \u4f60\u53ef\u4ee5\u5728 \u8fd9\u91cc \u627e\u5230\u6211\u7684 Travis \u914d\u7f6e\u3002\u5176\u4e2d\u5b9a\u4e49\u4e86\u4e09\u4e2a\u73af\u5883\u53d8\u91cf\uff1a\nenv: global: - DOCKER_USERNAME=wi1dcard # \u6211\u7684 Docker Hub \u7528\u6237\u540d - DOCKER_IMAGE=$DOCKER_USERNAME\/blog # Docker \u955c\u50cf\u540d - DOCKER_TAG=build-$TRAVIS_BUILD_NUMBER # Docker \u955c\u50cf Tag \u8fd9\u4e9b\u53d8\u91cf\u4f1a\u5728\u4e4b\u540e\u7528\u5230\u3002\n \u6ce8\u610f $DOCKER_TAG\uff0c\u5b83\u7684\u503c\u662f\u52a8\u6001\u7684\uff0c\u5373\u6bcf\u6b21\u6784\u5efa\u90fd\u4f1a\u53d8\u5316\uff0c\u7531 Travis CI \u7684 \u9884\u5b9a\u4e49\u73af\u5883\u53d8\u91cf \u62fc\u63a5\u800c\u6210\u3002\n \u5728 before_script \u5185\uff0c\u5b9a\u4e49\u4e86\u6784\u5efa\u8fc7\u7a0b\u7684\u811a\u672c\uff1a\nbefore_script: - build\/build.sh \u7531\u4e8e\u6784\u5efa\u3001\u53d1\u5e03\u8fc7\u7a0b\u6bd4\u8f83\u590d\u6742\uff0c\u540c\u65f6\u4e3a\u4e86\u672a\u6765\uff08\u53ef\u80fd\uff09\u8fc1\u79fb\u5230 GitLab CI\uff0c\u6211\u6ca1\u6709\u5c06\u6240\u6709\u811a\u672c\u7f57\u5217\u5728 .travis.yml \u91cc\u3002\u6240\u6709\u4e0e CI \u76f8\u5173\u7684\u5185\u5bb9\u6211\u90fd\u653e\u5728\u4e86 build\/ \u76ee\u5f55\u3002\nbuild\/build.sh \u7684\u4e3b\u8981\u4efb\u52a1\u662f\uff1a\n \u5b89\u88c5\u4f9d\u8d56\uff0c\u4f8b\u5982 Hexo\u3002 \u6267\u884c lint \u8fc7\u7a0b\uff0c\u68c0\u67e5 Markdown \u8bed\u6cd5\u7b49\u3002 \u6e32\u67d3\u9759\u6001\u7ad9\u70b9\uff0c\u751f\u6210 PDF \u683c\u5f0f\u7b80\u5386\u3002 \u6784\u5efa Docker \u955c\u50cf\u3002  \u53d1\u5e03 Docker \u955c\u50cf \u4e0e CD \u76f8\u5173\u7684\u5185\u5bb9\u6211\u653e\u5728\u4e86 deploy\/ \u76ee\u5f55\u3002\u6b63\u5982 .travis.yml \u5b9a\u4e49\u7684\u90a3\u6837\uff0c\u90e8\u7f72\u811a\u672c\u4f4d\u4e8e deploy\/deploy.sh\uff1a\nscript: - deploy\/deploy.sh \u9996\u5148\uff0c\u767b\u5f55 Docker Hub\uff0c\u63a5\u7740\u63a8\u9001\u955c\u50cf\uff1a\necho &#34;Logging in Docker Hub...&#34; echo &#34;$DOCKER_PASSWORD&#34; | docker login -u &#34;$DOCKER_USERNAME&#34; --password-stdin echo &#34;Pushing images to Docker Hub...&#34; docker push &#34;$DOCKER_IMAGE&#34; \u6ce8\u610f\uff0c\u8fd9\u91cc\u7528\u5230\u4e86\u4e4b\u524d\u5b9a\u4e49\u7684\u73af\u5883\u53d8\u91cf\u3002\u5176\u4e2d\uff0c$DOCKER_PASSWORD \u6211\u5b9a\u4e49\u5728 Travis CI \u7684\u79c1\u6709\u73af\u5883\u53d8\u91cf\u5185\uff1a\n\u8fd8\u6709\u4e24\u4e2a\u73af\u5883\u53d8\u91cf INGRESS_HOST \u548c KUBECONFIG_BASE64 \u7a0d\u540e\u4f1a\u7528\u5230\u3002\n\u5173\u4e8e Immutable \u4f60\u53ef\u4ee5\u5728 \u8fd9\u91cc \u67e5\u770b\u63a8\u9001\u7684\u955c\u50cf\u548c Tags\u3002\n\u8fd8\u8bb0\u5f97 $DOCKER_TAG \u7684\u503c\u662f\u52a8\u6001\u7684\u5417\uff0c\u6240\u4ee5\u6bcf\u6b21 CI \u6784\u5efa\u4ea7\u751f\u7684\u955c\u50cf\u90fd\u4f1a\u6709\u552f\u4e00\u7684 Tag \u4e0e\u5b83\u7684 Build ID \u5bf9\u5e94\u3002\n\u8fd9\u5bf9\u6211\u6765\u8bf4\u597d\u5904\u663e\u800c\u6613\u89c1\uff1a\n Immutable\u3002\u6bcf\u6b21\u6784\u5efa\u7684\u955c\u50cf\u5c31\u50cf Git Commit \u4e00\u6837\u7559\u4e0b\u4e0d\u53ef\u53d8\u66f4\u7684\u5370\u8bb0\u3002 \u6e05\u6670\u660e\u4e86\uff0c\u4e0d\u6613\u6df7\u6dc6\u3002\u4f60\u65e0\u6cd5\u5feb\u901f\u5f97\u77e5\u5f53\u524d lastet \u5177\u4f53\u662f\u54ea\u4e00\u6b21\u6784\u5efa\u7684\u4ea7\u7269\u3002 \u4fbf\u4e8e\u56de\u6eda\u3002\u867d\u7136\u4f60\u53ef\u4ee5\u91cd\u65b0\u6784\u5efa\u955c\u50cf\uff0c\u4f46\u5982\u679c\u4f60\u5c06\u6bcf\u6b21\u6784\u5efa\u7684\u955c\u50cf\u4fdd\u7559\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u5feb\u901f\u5730\u3001\u5b8c\u7f8e\u5730\u56de\u6eda\u5230\u4efb\u610f\u7248\u672c\uff08\u5c24\u5176\u80fd\u591f\u9632\u6b62\u540c\u4e00 Git Commit \u591a\u6b21 Build \u4ea7\u751f\u4e0d\u540c\u7684 Image\uff09\u3002 &hellip;   \u5176\u5b9e\uff0c\u505a\u4e86\u4e00\u5e74\u8fd0\u7ef4\u4e4b\u540e\u6211\u53d1\u73b0\uff0c\u6709\u65f6\u5019\u6df7\u6dc6\u6bd4\u300c\u6211\u4e0d\u77e5\u9053\u300d\u66f4\u53ef\u6015\u3002\u4e00\u4e9b\u9690\u6027\u7684\u58f0\u660e\u53ef\u80fd\u4f1a\u5bfc\u81f4\u4f60\u5728\u67d0\u4e2a\u6781\u5c0f\u7684\u95ee\u9898\u4e0a\uff0c\u6beb\u65e0\u610f\u4e49\u5730\u6d6a\u8d39\u4e00\u6574\u5929\u65f6\u95f4\u3002\u56e0\u6b64\u5982\u679c\u67d0\u4e9b\u65f6\u5019\u300c\u7b80\u6d01\u4f18\u96c5\u300d\u548c\u300c\u6e05\u6670\u660e\u4e86\u300d\u4ea7\u751f\u51b2\u7a81\u7684\u65f6\u5019\uff0c\u6211\u4f1a\u6beb\u4e0d\u72b9\u8c6b\u9009\u62e9 \u6e05\u6670\u660e\u4e86 \u5730\u663e\u5f0f\u58f0\u660e\uff0c\u5c3d\u7ba1\u73b0\u5728\u770b\u8d77\u6765\u53ef\u80fd\u6709\u70b9\u4e11\uff0c\u4f46\u672a\u6765\u8c03\u8bd5\u7684\u65f6\u5019\u53ef\u80fd\u4f1a\u5e2e\u4e0a\u5927\u5fd9\u3002\n \uff08\u672a\u5b8c\u5f85\u7eed\uff09\n","permalink":"https:\/\/wi1dcard.dev\/posts\/migrate-to-kubernetes-i\/","summary":"<p>\u6700\u8fd1 Kubernetes \u7684\u53d1\u5c55\uff0c\u4ee5\u53ca\u5728\u6211\u53f8\u7684\u5927\u91cf\u5e94\u7528\uff0c\u81ea\u5df1\u4e5f\u8feb\u4e0d\u53ca\u5f85\u60f3\u8981\u5c1d\u5c1d\u9c9c\uff0c\u867d\u7136\u6211\u7684\u535a\u5ba2\u662f\u57fa\u4e8e Hexo \u7684\u7eaf\u9759\u6001\u7ad9\u70b9\uff0c\u4f46\u8fd9\u5e76\u4e0d\u80fd\u963b\u6321\u6211\u628a\u5b83\u8fc1\u79fb\u4e0a Kubernetes\uff01\u6bd5\u7adf&hellip; \u76f8\u6bd4\u4e8e GitHub Pages \u7075\u6d3b\u6027\u66f4\u597d\u53ef\u63a7\u6027\u66f4\u9ad8\uff0cemmmm&hellip; \u597d\u4e86\u6211\u7f16\u4e0d\u4e0b\u53bb\u4e86\uff0c\u603b\u4e4b\uff0c\u751f\u547d\u5728\u4e8e\u6298\u817e\ud83d\ude02\uff0c\u6211\u4eec\u5f00\u59cb\u5427\u3002<\/p>","title":"\u6211\u5982\u4f55\u5c06\u535a\u5ba2\u8fc1\u79fb\u5230 Kubernetes - I"},{"content":"sudo spctl --master-disable ","permalink":"https:\/\/wi1dcard.dev\/posts\/disable-system-policy-on-macos\/","summary":"sudo spctl --master-disable ","title":"\u5141\u8bb8 macOS \u5b89\u88c5\u4efb\u4f55\u672a\u7b7e\u540d\u7684 App"},{"content":"\u5728\u8fd1\u671f\u6298\u817e\u79d1\u5b66\u4e0a\u7f51\u7f51\u5173\u7684\u8fc7\u7a0b\u4e2d\uff0c\u987a\u4fbf\u7814\u7a76\u4e86\u4e00\u4e0b VLAN\u3002\u901a\u8fc7\u9002\u5f53\u5730\u914d\u7f6e\uff0c\u4e00\u53f0\u53ea\u5177\u5907\u5355\u7269\u7406\u7f51\u53e3\u7684 NanoPi NEO2\uff0c\u540c\u6837\u53ef\u4ee5\u53d8\u8eab\u300c\u5355\u81c2\u300d\u8def\u7531\u5668\u3002\n\u51c6\u5907\u5de5\u4f5c  NanoPi NEO2 \u652f\u6301 802.1Q VLAN \u7684\u4ea4\u6362\u673a\uff08\u4f8b\u5982\u6211\u6b63\u5728\u4f7f\u7528\u7684 Netgear GS108Ev3\uff09  \u914d\u7f6e\u4ea4\u6362\u673a \u914d\u7f6e\u4ea4\u6362\u673a\u65e0\u975e\u5c31\u662f\u5212\u5206 VLAN \u7684\u8fc7\u7a0b\u3002\u6211\u5c06\u4ea4\u6362\u673a\u7684 8 \u4e2a\u7aef\u53e3\u5212\u5206\u4e3a\u4e24\u4e2a VLAN\uff0cID \u5206\u522b\u4e3a 1 \u548c 2\u3002\n\u5982\u4e0a\u56fe\u6240\u793a\uff0c\u5176\u4e2d\uff1a\n VLAN 1 \u4f5c\u4e3a WAN\uff0c\u5bf9\u5e94 1\u30012\u30013\u30014 \u53e3\u3002 VLAN 2 \u4f5c\u4e3a LAN\uff0c\u5bf9\u5e94 4\u30015\u30016\u30017\u30018 \u53e3\u3002  \u53ef\u4ee5\u770b\u51fa\uff0c\u7b2c 4 \u4e2a\u63a5\u53e3\u6a2a\u8de8\u4e24\u4e2a VLAN\uff0c\u968f\u540e\u6211\u4eec\u5c06\u4f1a\u628a NanoPi \u8fde\u63a5\u5230\u8be5\u63a5\u53e3\u4e0a\u3002\n\u540c\u65f6\uff0c\u6211\u5c06\u7b2c 4 \u4e2a\u63a5\u53e3\u914d\u7f6e\u4e3a Tagged VLAN\uff0c\u5176\u4f59\u63a5\u53e3\u5747\u914d\u7f6e\u4e3a Untagged\uff1a\n\u8fd9\u6837\uff0cNanoPi \u4fbf\u80fd\u901a\u8fc7 VLAN Tag \u83b7\u77e5\u6570\u636e\u5305\u7684\u6765\u6e90\u662f WAN\uff08VLAN 1\uff09\u8fd8\u662f LAN\uff08VLAN 2\uff09\uff1b\u540c\u65f6\uff0c\u4e5f\u53ef\u4ee5\u6807\u8bb0\u53d1\u51fa\u6570\u636e\u5305\u5e94\u5f53\u4f20\u8f93\u5230\u54ea\u4e2a VLAN\u3002\n \u63d0\u793a\uff1a\u5173\u4e8e VLAN Tag \u7684\u77e5\u8bc6\u8bf7\u81ea\u884c\u641c\u7d22\uff1b\u53e6\u5916\uff0c\u4ea4\u6362\u673a\u79c1\u6709\u7684\u3001\u57fa\u4e8e\u7aef\u53e3\u7684 VLAN \u4e0d\u652f\u6301 Tag \u529f\u80fd\uff0c\u52a1\u5fc5\u6ce8\u610f\u3002\n \u6700\u540e\uff0c\u914d\u7f6e\u63a5\u53e3\u9ed8\u8ba4\u7684 PVID\uff1a\n\u6ce8\u610f\u7b2c 4 \u4e2a\u63a5\u53e3\uff0c\u6211\u5c06\u5b83\u7684 PVID \u8bbe\u7f6e\u4e3a 2\uff0c\u4e5f\u5c31\u662f\u5bf9\u5e94 VLAN 2\uff1b\u5373\u6536\u5230\u7531\u8be5\u63a5\u53e3\u53d1\u6765\u7684\u4e0d\u5e26 VLAN Tag \u7684\u6570\u636e\u5305\uff0c\u5219\u9ed8\u8ba4\u8ba4\u4e3a\u5c5e\u4e8e VLAN 2\u3002\n\u914d\u7f6e NanoPi \u9996\u5148\u8fde\u63a5\u5230 NanoPi\uff0c\u521b\u5efa\u5bf9\u5e94 VLAN \u7684\u865a\u62df\u63a5\u53e3\uff1a\nnmcli conn add type vlan ifname WAN dev eth0 id 1 # VLAN 1 nmcli conn add type vlan ifname LAN dev eth0 id 2 # VLAN 2 \u7531\u4e8e NanoPi \u5728 LAN \u5185\u627f\u62c5\u8def\u7531\u7684\u5de5\u4f5c\uff0c\u56e0\u6b64\u9700\u8981\u914d\u7f6e\u4e3a\u9759\u6001 IP\uff1a\nnmcli conn mod vlan-LAN \\ ipv4.method manual \\ ipv4.addresses 192.168.88.1\/24 \\ ipv4.gateway 192.168.88.1 \\ ipv4.dns 192.168.88.1 \u5176\u4e2d 192.168.88.1 \u662f LAN \u7684\u7f51\u5173 IP\uff08\u4e5f\u5c31\u662f NanoPi \u81ea\u8eab\u7684 IP \u5566\uff09\uff0c\/24 \u4e3a LAN \u7684\u5b50\u7f51 CIDR \u524d\u7f00\u3002\n\u63a5\u4e0b\u6765\uff0c\u505c\u6b62 Systemd \u63d0\u4f9b\u7684\u672c\u5730 DNS \u7f13\u5b58\u670d\u52a1 systemd-resolved\uff0c\u4f7f\u7528 DNSMASQ \u4ee3\u66ff\uff1a\nsystemctl stop systemd-resolved systemctl disable systemd-resolved apt install dnsmasq \u5e76\u4fee\u6539 \/etc\/dnsmasq.conf\uff0c\u914d\u7f6e DHCP \u670d\u52a1\u548c DNS \u670d\u52a1\uff1a\n# \u4ec5\u5bf9 LAN \u63d0\u4f9b\u670d\u52a1 interface=LAN # \u4e0d\u8bfb\u53d6 \/etc\/resolv.conf \u4f5c\u4e3a\u4e0a\u6e38 DNS \u670d\u52a1\u5668 no-resolv # \u914d\u7f6e\u4e0a\u6e38 DNS \u670d\u52a1\u5668\u4e3a 114.114.114.114 server=114.114.114.114 # DNS \u8bb0\u5f55\u7f13\u5b58\u6570\u91cf\u4e3a 10000 cache-size=10000 # DHCP IP \u8303\u56f4\uff0c\u7531 192.168.88.50 \u5230 192.168.88.150 # \u5b50\u7f51\u63a9\u7801\u4e3a 255.255.255.0\uff0cDHCP \u79df\u7ea6\u6709\u6548\u671f\u4e3a 1 \u5c0f\u65f6 dhcp-range=192.168.88.50,192.168.88.150,255.255.255.0,1h # DHCP \u9009\u9879\uff0c\u4e0b\u53d1\u7ed9\u5ba2\u6237\u7aef\u7684 DNS \u670d\u52a1\u5668\u4e3a 192.168.88.1 dhcp-option=option:dns-server,192.168.88.1 \u53e6\u5916\uff0c\u8fd8\u9700\u8981\u914d\u7f6e iptables\uff0c\u5b9e\u73b0\u8def\u7531\u5668\u6700\u91cd\u8981\u7684\u529f\u80fd \u2014\u2014 NAT\uff1a\n# \u589e\u52a0\u89c4\u5219 iptables -t nat -A POSTROUTING -o WAN -j MASQUERADE # \u6301\u4e45\u5316\u89c4\u5219 apt install iptables-persistent netfilter-persistent netfilter-persistent save \u6700\u540e\uff0c\u5f00\u542f\u5185\u6838 IPv4 \u6570\u636e\u5305\u8f6c\u53d1\u5373\u53ef\uff1a\nsed -i -E 's\/#?\\s*(net.ipv4.ip_forward)(.*)$\/\\1 = 1\/' \/etc\/sysctl.conf sysctl -p \/etc\/sysctl.conf \u53c2\u8003\u8d44\u6599  https:\/\/www.liangshuang.name\/2018\/09\/05\/router-on-a-stick-with-raspberrypi-shadowsocks\/ https:\/\/access.redhat.com\/documentation\/en-us\/red_hat_enterprise_linux\/7\/html\/networking_guide\/sec-configure_802_1q_vlan_tagging_using_the_command_line_tool_nmcli ","permalink":"https:\/\/wi1dcard.dev\/posts\/configure-nanopi-as-a-router\/","summary":"<p>\u5728\u8fd1\u671f\u6298\u817e\u79d1\u5b66\u4e0a\u7f51\u7f51\u5173\u7684\u8fc7\u7a0b\u4e2d\uff0c\u987a\u4fbf\u7814\u7a76\u4e86\u4e00\u4e0b VLAN\u3002\u901a\u8fc7\u9002\u5f53\u5730\u914d\u7f6e\uff0c\u4e00\u53f0\u53ea\u5177\u5907\u5355\u7269\u7406\u7f51\u53e3\u7684 NanoPi NEO2\uff0c\u540c\u6837\u53ef\u4ee5\u53d8\u8eab\u300c\u5355\u81c2\u300d\u8def\u7531\u5668\u3002<\/p>","title":"\u5c06 NanoPi \u914d\u7f6e\u4e3a\u5355\u81c2\u8def\u7531\u5668"},{"content":"\u4ece\u4e8b\u8fd0\u7ef4\u5de5\u7a0b\u5e08\uff08\u517c\u516c\u53f8\u7f51\u7ba1\ud83d\ude02\uff09\u4ee5\u6765\uff0c\u9047\u5230\u4e0d\u5c11\u5404\u5f0f\u5404\u6837\u7684\u7f51\u7edc\u6545\u969c\uff0c\u6709\u7684\u6765\u81ea\u4e8e\u8def\u7531\u5668\u95ee\u9898\uff0c\u6709\u7684\u5219\u662f\u5ba2\u6237\u7aef\u914d\u7f6e\u9519\u8bef\u3002\u800c\u5f00\u53d1\u4eba\u5458\u7684\u53cd\u9988\u5927\u591a\u7c7b\u4f3c\u4e8e\uff1a\n \u300c\u6211\u4e0a\u4e0d\u4e86\u7f51\u4e86\uff01\u300d \u300c\u7f51\u7edc\u5361\u4e86\u5417\uff1f\u4e00\u76f4\u5728\u52a0\u8f7d&hellip;\u300d  \u4fe1\u606f\u91cf\u7a0d\u591a\u4e00\u70b9\u7684\u4f8b\u5982\uff1a\n \u300cping \u4e0d\u901a\u67d0\u67d0\u5730\u5740\u300d \u300cChrome \u663e\u793a\u67d0\u67d0\u9519\u8bef\u300d  \u7b49\u7b49\u8bf8\u5982\u6b64\u7c7b\u3002\n\u7136\u800c\uff0c\u8fd9\u4e9b\u5bf9\u4e8e\u7f51\u7edc\u5de5\u7a0b\u5e08\u6765\u8bf4\u5e76\u6ca1\u6709\u4efb\u4f55\u4ef7\u503c\u3002\u4f60\u8868\u8ff0\u7684\u662f\u300c\u73b0\u8c61\u300d\uff0c\u5e76\u4e0d\u662f\u300c\u7ebf\u7d22\u300d\uff0c\u901a\u8fc7\u8fd9\u5be5\u5be5\u65e0\u51e0\u7684\u8bed\u53e5\uff0c\u4ed6\u4eec\u65e0\u6cd5\u5feb\u901f\u5730\u8c03\u67e5\u6545\u969c\u539f\u56e0\u3002\u5c31\u597d\u50cf\u4f60\u5f00\u53d1\u7684\u5e94\u7528\u65e0\u6cd5\u6b63\u5e38\u5de5\u4f5c\uff0c\u800c\u6d4b\u8bd5\u5de5\u7a0b\u5e08\u7684\u53cd\u9988\u5e76\u6ca1\u6709\u8be6\u7ec6\u7684\u62a5\u9519\u4fe1\u606f\uff0c\u53ea\u6709\u300c\u72b6\u6001\u7801 500\u300d\u4e00\u6837\u3002\n\u800c\u672c\u6587\uff0c\u5c31\u662f\u60f3\u901a\u8fc7\u5e38\u89c1\u7684\u573a\u666f\uff0c\u6765\u5f15\u5bfc\u5927\u5bb6\u5feb\u901f\u5730\u5b9a\u4f4d\u672c\u5730\u7f51\u7edc\u6545\u969c\u3002\u5728\u8d1f\u8d23\u7f51\u7edc\u7684\u540c\u4e8b\u8fd8\u6ca1\u6709\u300c\u7a7a\u964d\u300d\u5230\u4f60\u7535\u8111\u4e4b\u524d\uff0c\u5c3d\u53ef\u80fd\u628a\u53ef\u80fd\u7684\u539f\u56e0\u7f29\u5c0f\u5230\u6bd4\u8f83\u5bb9\u6613\u6392\u67e5\u7684\u533a\u95f4\u3002\u5373\u4fbf\u4f5c\u4e3a\u5f00\u53d1\u8005\u53ef\u80fd\u65e0\u6cd5\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\uff0c\u4f46\u4e5f\u80fd\u7ed9\u7f51\u7edc\u5de5\u7a0b\u5e08\u4eec\u63d0\u4f9b\u6781\u5927\u7684\u5e2e\u52a9\uff0c\u8bf4\u4e0d\u5b9a\u4ed6\u4eec\u4f1a\u5bf9\u4f60\u522e\u76ee\u76f8\u770b\u7684\u3002\n\u6d4f\u89c8\u5668\u4e0e CURL \u901a\u5e38\u6765\u8bf4\uff0c\u53d1\u73b0\u7f51\u7edc\u6545\u969c\u7684\u300c\u5165\u53e3\u300d\u5927\u591a\u662f\u6d4f\u89c8\u5668\u6253\u4e0d\u5f00\u67d0\u4e2a\u7f51\u7ad9\u4e86\u3002\n\u4ee5 Chrome \u4e3a\u4f8b\uff0c\u9519\u8bef\u9875\u9762\u53ef\u80fd\u662f\u8fd9\u6837\u7684\uff1a\n\u9996\u5148\uff0c\u4f60\u9700\u8981\u786e\u8ba4\u662f\u5bf9\u65b9\uff08\u670d\u52a1\u7aef\uff09\u8fd8\u662f\u4f60\u7684\u7f51\u7edc\u95ee\u9898\uff0c\u4f60\u53ef\u4ee5\u5c1d\u8bd5\u8bbf\u95ee\u767e\u5ea6\u3001\u817e\u8baf\u4e4b\u7c7b\u7684\u7f51\u7ad9\uff0c\u8fd9\u4e9b\u7ad9\u70b9\u672c\u8eab\u6545\u969c\u7684\u6982\u7387\u975e\u5e38\u4f4e\uff0c\u5982\u679c\u8fde\u7eed\u8bbf\u95ee\u51e0\u4e2a\u7ad9\u70b9\u90fd\u6253\u4e0d\u5f00\uff0c\u90a3\u4e48\u4f60\u53ef\u4ee5\u7ee7\u7eed\u5f80\u4e0b\u770b\u4e86\u3002\n\u6d4f\u89c8\u5668\u8bbf\u95ee\u7f51\u7ad9\u6700\u91cd\u8981\u7684\u6b65\u9aa4\u4e4b\u4e00\u5c31\u662f\u53d1\u8d77 HTTP \u8bf7\u6c42\u3002\u4f46\u5176\u5b9e\u5728\u8f93\u5165\u5730\u5740\u6309\u4e0b\u56de\u8f66\u540e\uff0c\u76f4\u5230\u7f51\u9875\u5c55\u793a\u5728\u4f60\u7684\u9762\u524d\uff0c\u8fd9\u5176\u4e2d\u6d4f\u89c8\u5668\u8fd8\u505a\u4e86\u5927\u91cf\u7684\u5de5\u4f5c\uff08\u6709\u5174\u8da3\u53ef\u81ea\u884c\u641c\u7d22\u8be5\u7ecf\u5178\u9762\u8bd5\u9898\uff09\u3002\u4f7f\u7528\u6d4f\u89c8\u5668\u8c03\u8bd5\u7f51\u7edc\u95ee\u9898\u7684\u4e0d\u53ef\u63a7\u56e0\u7d20\u592a\u591a\uff0c\u8bf8\u5982\u5404\u7c7b\u7f13\u5b58\u673a\u5236\u3001\u9884\u52a0\u8f7d\u7b49\u7b49\u3002\u53e6\u5916\u4e0d\u540c\u6d4f\u89c8\u5668\u7684\u884c\u4e3a\u6216\u591a\u6216\u5c11\u5b58\u5728\u5dee\u522b\uff0c\u62a5\u9519\u4fe1\u606f\u4e5f\u4e0d\u5c3d\u76f8\u540c\u3002\u56e0\u6b64\uff0c\u8bf7\u4f7f\u7528 CURL \u5de5\u5177\u53d1\u8d77\u539f\u59cb\u7684 HTTP \u8bf7\u6c42\uff0c\u6bd4\u5982\uff1a\ncurl -v --noproxy &#34;*&#34; www.baidu.com \u5176\u4e2d\uff1a\n -v \u8868\u793a\u5f00\u542f\u5570\u55e6\u6a21\u5f0f\uff0c\u5c3d\u53ef\u80fd\u591a\u5730\u8f93\u51fa\u4fe1\u606f\u4ee5\u4fbf\u8c03\u8bd5\u3002 --noproxy &quot;*&quot; \u8868\u793a\u5bf9\u6240\u6709\u7ad9\u70b9\u7981\u7528\u4ee3\u7406\uff0c\u5982\u679c\u4f60\u7684\u547d\u4ee4\u884c\u73af\u5883\u8bbe\u7f6e\u4e86\u8bf8\u5982 http_proxy\u3001socks5_proxy\u3001all_proxy \u7b49\u73af\u5883\u53d8\u91cf\uff0c\u8be5\u9009\u9879\u53ef\u4ee5\u4fdd\u8bc1 curl \u547d\u4ee4\u4e0d\u4f7f\u7528\u4efb\u4f55\u4ee3\u7406\uff0c\u56e0\u6b64\u53ef\u4ee5\u907f\u514d\u53d7\u5230\u4ee3\u7406\u670d\u52a1\u5668\u7684\u5f71\u54cd\u3002  \u5982\u679c CURL \u6b63\u5e38\u8fd0\u884c\uff0c\u8f93\u51fa\u4e86\u4e00\u5927\u6bb5 HTML \u4e4b\u7c7b\u7684\u6570\u636e\uff0c\u90a3\u4e48\u95ee\u9898\u6709\u53ef\u80fd\u51fa\u5728\uff1a\n \u6d4f\u89c8\u5668\u95ee\u9898\u3002\u6bd4\u5982\u6d4f\u89c8\u5668\u8bbe\u7f6e\u9519\u8bef\uff0c\u6216\u662f\u88c5\u4e86\u67d0\u4e9b\u5b58\u5728 BUG \u7684\u63d2\u4ef6\uff0c\u53ef\u4ee5\u6362\u4e2a\u6d4f\u89c8\u5668\u6216\u4f7f\u7528\u9690\u8eab\u6a21\u5f0f\u518d\u5c1d\u8bd5\u3002\u8be5\u7c7b\u95ee\u9898\u4e0d\u5728\u672c\u6587\u8ba8\u8bba\u8303\u56f4\u5185\u3002 \u7cfb\u7edf\u4ee3\u7406\u914d\u7f6e\u95ee\u9898\u3002\u4ee5 macOS \u4e3a\u4f8b\uff0c\u5728\u300c\u7cfb\u7edf\u504f\u597d\u8bbe\u7f6e\u300d-\u300c\u7f51\u7edc\u300d-\u300c\u9ad8\u7ea7\u300d-\u300c\u4ee3\u7406\u300d\u6807\u7b7e\u9875\u5185\uff0c\u53ef\u80fd\u914d\u7f6e\u4e86\u9519\u8bef\u7684\u4ee3\u7406\u670d\u52a1\u5668\u3002\u573a\u666f\u4e3e\u4f8b\uff1a\u5728 macOS \u5f3a\u884c\u91cd\u542f\u540e\uff0c\u50cf ShadowsocksX-NG\u3001Charles\u3001Fiddler \u7b49\u5de5\u5177\u672a\u6b63\u5e38\u9000\u51fa\uff0c\u5bfc\u81f4\u8fd0\u884c\u65f6\u4fee\u6539\u4e86\u7cfb\u7edf\u4ee3\u7406\u670d\u52a1\u5668\u4f46\u6ca1\u6709\u8fd8\u539f\uff0c\u56e0\u6b64\u65e0\u6cd5\u4e0a\u7f51\u3002  \u5982\u679c CURL \u62a5\u9519\uff0c\u6211\u4eec\u5927\u81f4\u53ef\u5206\u4e3a\u4e09\u7c7b\uff1a\n  HTTP \u95ee\u9898\n \u4f8b\u5982\u5404\u7c7b\u72b6\u6001\u7801 302 \/ 403 \/ 502 \u7b49\u3002\u51fa\u73b0\u6b64\u7c7b\u95ee\u9898\u591a\u6570\u662f\u7531\u4e8e\u670d\u52a1\u7aef\u914d\u7f6e\u4e0d\u5f53\u5bfc\u81f4\uff0c\u9664\u975e\u4f60\u8bf7\u6c42\u6240\u6709\u7684\u7f51\u7ad9\u90fd\u8fd4\u56de\u540c\u6837\u7684\u9519\u8bef\u72b6\u6001\u7801\uff0c\u5426\u5219\u51e0\u4e4e\u4e0d\u53ef\u80fd\u662f\u672c\u5730\u7f51\u7edc\u539f\u56e0\u3002\u552f\u4e00\u6211\u80fd\u591f\u60f3\u5230\u7684\u53ef\u80fd\u6027\uff0c\u5c31\u662f\u4f60\u7684\u7f51\u7edc\u906d\u5230\u4e86\u52ab\u6301\u6216\u7be1\u6539\uff08\u6216\u8bb8\u662f\u7f51\u7edc\u5de5\u7a0b\u5e08\u6545\u610f\u4e3a\u4e4b\uff09\u3002    DNS \u95ee\u9898\n \u5728 Rebuilt URL to: ... \u5361\u4f4f\uff1a\u6b64\u65f6 CURL \u53ef\u80fd\u5728\u53d1\u9001 DNS \u8bf7\u6c42\uff0c\u5c1d\u8bd5\u5c06\u57df\u540d\u89e3\u6790\u4e3a IP \u5730\u5740\uff0c\u7136\u800c DNS \u670d\u52a1\u5e76\u6ca1\u6709\u7ed9\u4e88\u54cd\u5e94\uff0c\u9700\u8981\u66f4\u6df1\u5165\u5730\u6392\u67e5\u3002 curl: (6) Could not resolve host: ***\uff1aDNS \u670d\u52a1\u53d1\u56de\u4e86\u54cd\u5e94\uff0c\u4f46\u65e0\u6cd5\u89e3\u6790\u8fd9\u4e2a\u57df\u540d\uff08\u6ca1\u6709\u8be5\u8bb0\u5f55\uff09\u3002\u573a\u666f\u4e3e\u4f8b\uff1aDNS \u670d\u52a1\u5668\u7684\u4e0a\u6e38\u670d\u52a1\u5668\u914d\u7f6e\u9519\u8bef\uff0c\u5bfc\u81f4\u65e0\u6cd5\u4ece\u4e0a\u6e38\u670d\u52a1\u5668\u83b7\u53d6\u89e3\u6790\u7ed3\u679c\u3002    TCP \u95ee\u9898\n curl: (52) Empty reply from server\uff1a\u670d\u52a1\u7aef\u63a5\u53d7\u4e86\u8fde\u63a5\uff0c\u4f46\u5e76\u6ca1\u6709\u53d1\u4efb\u4f55\u56de\u590d\u5c31\u65ad\u5f00\u4e86\u3002\u573a\u666f\u4e3e\u4f8b\uff1a\u8def\u7531\u5668\u79d1\u5b66\u4e0a\u7f51\uff0c\u4f46\u5bc6\u7801\u914d\u7f6e\u9519\u4e86\uff1b\u7f51\u5173\uff08\u79d1\u5b66\u4e0a\u7f51\u7684\u8def\u7531\u5668\uff09\u63a5\u5230\u8fde\u63a5\u4e4b\u540e\u7acb\u5373\u63a5\u53d7\uff0c\u7531\u4e8e\u5bc6\u7801\u9519\u8bef\u5bfc\u81f4\u65e0\u6cd5\u4e0e\u4ee3\u7406\u670d\u52a1\u5668\u6b63\u5e38\u5efa\u7acb\u8fde\u63a5\uff0c\u56e0\u6b64\u53ea\u597d\u5565\u4e5f\u4e0d\u56de\u590d\u5c31\u65ad\u5f00\u3002\u5982\u679c\u4f60 CURL \u7684\u5730\u5740\u662f\u4f60\u81ea\u5df1\u7684\u670d\u52a1\uff0c\u90a3\u4e48\u6709\u53ef\u80fd\u662f\u534f\u8bae\u4e0d\u5bf9\uff0c\u5bf9\u9762\u76d1\u542c\u7684\u6216\u8bb8\u5e76\u4e0d\u662f HTTP \u534f\u8bae\u3002 curl: (7) Failed to connect to *** port 80: Connection refused\uff1a\u670d\u52a1\u7aef\u76f4\u63a5\u62d2\u7edd\u4e86\u8fde\u63a5\u3002\u573a\u666f\u4e3e\u4f8b\uff1a\u9632\u706b\u5899\u3002\u65e0\u8bba\u662f\u7535\u8111\u7684\u9632\u706b\u5899\u8fd8\u662f\u8def\u7531\u5668\u3001\u4ea4\u6362\u673a\u751a\u81f3\u670d\u52a1\u5668\u7684\u9632\u706b\u5899\uff0c\u5982\u679c\u8be5\u76ee\u6807\u7aef\u53e3\u88ab\u9632\u706b\u5899\u62e6\u622a\uff0c\u90a3\u4e48\u6709\u53ef\u80fd\u51fa\u73b0\u6b64\u95ee\u9898\u3002 \u5728 Trying xx.xx.xx.xxx... \u5361\u4f4f\uff1a\u670d\u52a1\u7aef\u4e00\u76f4\u6ca1\u6709\u63a5\u53d7\u8fde\u63a5\uff0c\u4e5f\u6ca1\u6709\u4efb\u4f55\u56de\u5e94\u3002\u573a\u666f\u4e3e\u4f8b\uff1a\u8def\u7531\u5668\u65ad\u7f51\u3002\u4f8b\u5982 PPPoE \u62e8\u53f7\u5931\u8d25\uff0c\u5149\u732b\u6545\u969c\u7b49\u3002 curl: (7) Couldn't connect to server\uff1a\u65e0\u6cd5\u8fde\u63a5\u5230\u670d\u52a1\u5668\uff0c\u9700\u8981\u66f4\u6df1\u5165\u5730\u6392\u67e5\u3002    DNS \u4e0a\u6587\u4e2d\u63d0\u5230\u7684 DNS \u6545\u969c\u5927\u6982\u53ef\u4ee5\u5206\u4e3a\u4e24\u79cd\u60c5\u51b5\uff1a\n DNS \u670d\u52a1\u53d1\u56de\u54cd\u5e94\uff0c\u4f46\u89e3\u6790\u5931\u8d25\u3002 DNS \u670d\u52a1\u6ca1\u6709\u54cd\u5e94\u3002  \u5728\u7ee7\u7eed\u9605\u8bfb\u4e4b\u524d\uff0c\u5efa\u8bae\u4f60\u5148\u53bb\u7cfb\u7edf\u8bbe\u7f6e\u91cc\u770b\u770b DNS \u670d\u52a1\u7684 IP \u5730\u5740\u662f\u5426\u914d\u7f6e\u6b63\u786e\uff0c\u5982\u679c\u4f60\u662f\u624b\u52a8\u8bbe\u7f6e\u800c\u975e\u4f7f\u7528 DHCP \u4e0b\u53d1\u7684 DNS \u670d\u52a1\uff0c\u90a3\u4e48\u8bf7\u786e\u4fdd\u4f60\u8bbe\u7f6e\u7684 DNS \u670d\u52a1\u5668\u8fd0\u884c\u6b63\u5e38\u3002\n\u7531\u4e8e DNS \u534f\u8bae\u57fa\u4e8e UDP\uff0c\u6ca1\u6709 TCP \u5efa\u7acb\u8fde\u63a5\u7684\u6982\u5ff5\uff0c\u56e0\u6b64\u4e5f\u4e0d\u5b58\u5728 Connection refused \u7b49\u9519\u8bef\uff0c\u6240\u4ee5\u6211\u4eec\u65e0\u6cd5\u5f97\u77e5 DNS \u670d\u52a1\u6b64\u65f6\u7684\u72b6\u6001\u5982\u4f55\u3002\u4e0d\u8fc7\uff0c\u6709\u4e2a\u540d\u53eb dig \u7684\u5de5\u5177\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u4e3b\u52a8\u53d1\u8d77 DNS \u8bf7\u6c42\u3002\u4f8b\u5982\uff1a\ndig www.baidu.com # \u4f7f\u7528\u7cfb\u7edf\u9ed8\u8ba4 DNS \u670d\u52a1\u5668\u89e3\u6790 www.baidu.com dig www.baidu.com @114.144.114.114 # \u4f7f\u7528 114.114.114.114 \u89e3\u6790 \u5982\u679c\u7cfb\u7edf\u9ed8\u8ba4\u7684 DNS \u670d\u52a1\u5668\u6709\u95ee\u9898\uff0c\u4e5f\u53ef\u4ee5\u8bd5\u8bd5 114.114.114.114\u3001180.76.76.76 \u7b49\u77e5\u540d\u516c\u5171 DNS\u3002\u540c\u6837\uff0c\u8fd9\u4e9b\u670d\u52a1\u672c\u8eab\u6545\u969c\u7684\u6982\u7387\u975e\u5e38\u4f4e\u3002\n\u89e3\u6790\u6210\u529f\u7684\u8f93\u51fa\u7c7b\u4f3c\uff1a\nwww.baidu.com. 491 IN CNAME www.a.shifen.com. www.a.shifen.com. 134 IN A 182.61.200.7 www.a.shifen.com. 134 IN A 182.61.200.6 \u53d1\u56de\u54cd\u5e94\u4f46\u89e3\u6790\u5931\u8d25\u7c7b\u4f3c\uff1a\n;www.baidu.com. IN A \u82e5\u6ca1\u6709\u6536\u5230\u54cd\u5e94\uff0cdig \u5c06\u4f1a\u7ee7\u7eed\u7b49\u5f85\u3002\u4e00\u822c\u6765\u8bf4\uff0cDNS \u670d\u52a1\u5927\u591a\u80fd\u591f\u5728\u51e0\u767e\u6beb\u79d2\u5185\u53d1\u56de\u54cd\u5e94\uff0c\u5982\u679c\u51e0\u79d2\u949f\u540e\u4f9d\u7136\u5361\u7740\uff0c\u90a3\u53ef\u80fd\u662f\uff1a\n DNS \u670d\u52a1\u6302\u4e86\u3002 UDP \u6570\u636e\u5305\u5728\u67d0\u4e2a\u73af\u8282\u88ab\u9632\u706b\u5899\u62e6\u622a\u6216\u4e22\u5f03\u3002 DNS \u670d\u52a1\u7684 IP \u5728\u7f51\u7edc\u4e2d\u4e0d\u5b58\u5728\uff0c\u6570\u636e\u5305\u65e0\u6cd5\u5230\u8fbe\u3002  \u770b\u5230\u8fd9\u91cc\uff0c\u5982\u679c\u80fd\u591f\u786e\u8ba4\u4f60\u7684 DNS \u914d\u7f6e\u65e0\u8bef\uff0c\u90a3\u4e48\u4f60\u53ef\u4ee5\u5c06\u4f60\u7684 DNS \u670d\u52a1\u5668 IP \u5730\u5740\u544a\u77e5\u7f51\u7edc\u5de5\u7a0b\u5e08\u4e86\u3002\u540c\u65f6\uff0c\u6700\u597d\u76f4\u63a5\u5c06 dig \u547d\u4ee4\u7684\u8f93\u51fa\u539f\u5c01\u4e0d\u52a8\u7684\u53d1\u7ed9\u4ed6\u4eec\u3002\nTCP \u534f\u8bae \u5982\u679c\u4f60\u786e\u5b9a\u95ee\u9898\u51fa\u5728 TCP \u534f\u8bae\u5c42\uff0c\u90a3\u4e48\u6709\u4e2a\u5de5\u5177\u63a8\u8350\uff1atelnet\u3002\u4f7f\u7528 telnet \u76f8\u6bd4\u4e8e CURL \u80fd\u591f\u66f4\u65b9\u4fbf\u5730\u6d4b\u8bd5\u7aef\u53e3\u662f\u5426\u7545\u901a\u3002\u4f8b\u5982\uff1a\ntelnet 1.1.1.1 80 \u4ee5\u4e0a\u547d\u4ee4 telnet \u5c06\u4f1a\u5c1d\u8bd5\u4e0e 1.1.1.1 \u7684 80 \u7aef\u53e3\u5efa\u7acb\u8fde\u63a5\uff0c\u6b64\u5904\u4e0d\u4f7f\u7528\u57df\u540d\u662f\u4e3a\u4e86\u907f\u514d\u53d7\u5230 DNS \u670d\u52a1\u7684\u5f71\u54cd\u3002\u4f60\u53ef\u4ee5\u591a\u5c1d\u8bd5\u51e0\u4e2a\u5730\u5740\u548c\u7aef\u53e3\uff0c\u4f8b\u5982\u5e38\u7528\u7684 80\u3001443\u300122 \u7b49\u3002\n\u5047\u8bbe\u6210\u529f\u5efa\u7acb TCP \u8fde\u63a5\uff0c\u8f93\u51fa\u5c06\u4f1a\u7c7b\u4f3c\uff1a\nTrying 1.1.1.1... Connected to one.one.one.one. Escape character is '^]'. \u7136\u540e telnet \u4e0d\u4f1a\u9000\u51fa\uff0c\u800c\u662f\u7b49\u5f85\u4f60\u7ee7\u7eed\u8f93\u5165\uff1b\u4f60\u8f93\u5165\u7684\u5185\u5bb9\u5c06\u4f1a\u88ab\u53d1\u9001\u5230\u670d\u52a1\u7aef\uff0c\u800c\u670d\u52a1\u7aef\u7684\u54cd\u5e94\u540c\u6837\u4f1a\u663e\u793a\u5728\u547d\u4ee4\u884c\u4e2d\u3002\n\u8fd9\u91cc\u6709\u4e2a\u5c0f\u628a\u620f\uff0c\u4f60\u53ef\u4ee5\u76f4\u63a5\u624b\u52a8\u300c\u7f16\u5199\u300d\u4e00\u4e2a HTTP \u8bf7\u6c42\uff0c\u4f8b\u5982\uff1a\nGET \/ HTTP\/1.1 Host: www.baidu.com [\u6362\u884c] [\u6362\u884c] \u8bf7\u7559\u7a7a\uff0c\u5b9e\u9645\u5c31\u662f\u591a\u6309\u4e00\u4e0b\u56de\u8f66\uff0c\u8868\u793a HTTP \u8bf7\u6c42\u7ed3\u675f\uff0c\u5f00\u59cb\u7b49\u5f85\u670d\u52a1\u5668\u54cd\u5e94\u3002\u7a0d\u7b49\u7247\u523b\uff0c\u4f60\u4f1a\u770b\u5230 telnet \u8f93\u51fa\u4e86 HTTP \u54cd\u5e94\u5934\u548c\u4e00\u5927\u5806 HTML\u3002\n \u5982\u679c\u4f60\u5bf9 TCP \u534f\u8bae\u8db3\u591f\u4e86\u89e3\uff0c\u53ef\u4ee5\u5c1d\u8bd5 tcpdump\u3001Termshark \u4ee5\u53ca Wireshark\uff0c\u66f4\u52a0\u6df1\u5165\u5730\u5206\u6790 TCP \u63e1\u624b\u7684\u8fc7\u7a0b\uff0c\u5728\u6b64\u4e0d\u518d\u5c55\u5f00\u3002\n \u82e5\u662f\u65e0\u6cd5\u5efa\u7acb\u8fde\u63a5\u6216\u8005\u5efa\u7acb\u8fde\u63a5\u540e\u7acb\u523b\u65ad\u5f00\uff0ctelnet \u5c06\u4f1a\u8f93\u51fa\u5177\u4f53\u7684\u4fe1\u606f\u3002\u5982\u679c\u51fa\u73b0\u8bf8\u5982 Connection refused\u3001Connection closed by foreign host \u7b49\u63d0\u793a\uff0c\u8bf4\u660e\u81f3\u5c11\u6211\u4eec\u6536\u5230\u4e86\u670d\u52a1\u5668\u53d1\u56de\u7684 TCP \u54cd\u5e94\uff08\u6ce8\u610f\u4e0d\u662f HTTP\uff09\uff0c\u6b64\u65f6\u4f60\u53ef\u80fd\u9700\u8981\u53ec\u5524\u7f51\u7edc\u5de5\u7a0b\u5e08\uff0c\u544a\u8bc9\u4ed6\u4eec\u4f60\u672c\u673a\u53d1\u51fa\u7684 TCP \u8fde\u63a5\u88ab\u8fdc\u7aef\u62d2\u7edd\u6216\u662f\u4e3b\u52a8\u5173\u95ed\uff0c\u8ba9\u4ed6\u4eec\u8c03\u67e5\u4e00\u4e0b\u9632\u706b\u5899\u662f\u5426\u914d\u7f6e\u6709\u8bef\u4e86\u3002\n\u4e0d\u8fc7\u8fd9\u91cc\u6709\u4e2a\u7279\u6b8a\u60c5\u51b5\uff0c\u5982\u679c\u4f60\u7684\u62a5\u9519\u4e2d\u542b\u6709\u7c7b\u4f3c Network is unreachable \u7684\u5173\u952e\u5b57\uff0c\u90a3\u4e48\u6709\u4e24\u5927\u53ef\u80fd\u6027\uff1a\n \u4f60\u7684 Wi-Fi \u6216\u8005\u7f51\u7ebf\u65ad\u4e86\u3002 \u4f60\u672c\u5730\u7684 IP \u6216\u300c\u7f51\u5173\uff08\u90e8\u5206\u7cfb\u7edf\u79f0\u4f5c\u8def\u7531\u5668\uff09\u300d\u914d\u7f6e\u6709\u8bef\u3002\u4f60\u9700\u8981\u786e\u8ba4\u4f60\u4f7f\u7528\u7684\u662f DHCP \u4e0b\u53d1\u7684\u7f51\u5173\uff0c\u800c\u4e0d\u662f\u81ea\u5df1\u624b\u52a8\u914d\u7f6e\u7684\u3002\u53e6\u5916\uff0c\u5982\u679c\u4f60\u7684 IP \u5730\u5740\u662f 169.254 \u5f00\u5934\uff0c\u90a3\u4e48\u591a\u534a\u662f\u7f51\u7edc\u5185\u7684 DHCP \u670d\u52a1\u51fa\u73b0\u95ee\u9898\uff0c\u6216\u662f\u538b\u6839\u4e0d\u5b58\u5728 DHCP \u670d\u52a1\u3002\u8bf7\u76f4\u63a5\u547c\u53eb\u7f51\u7ba1\uff0c\u544a\u8bc9\u4ed6\u4eec\u4f60\u7684\u7535\u8111\u65e0\u6cd5\u83b7\u53d6 IP \u5730\u5740\u5427\u3002  \u5982\u679c\u4e00\u76f4\u5361\u5728 Trying ... \u800c\u6ca1\u6709 Connected to ...\uff0c\u90a3\u4e48\u8bf7\u7ee7\u7eed\u5f80\u4e0b\u770b\u3002\nICMP \u534f\u8bae \u6211\u4eec\u5e73\u65f6\u7ecf\u5e38\u4f7f\u7528\u7684 ping \u547d\u4ee4\u5c31\u662f\u57fa\u4e8e ICMP \u534f\u8bae\u7684\u3002\u76f8\u6bd4\u4e8e TCP\uff0c\u5b83\u4e0d\u5b58\u5728\u7aef\u53e3\u7684\u6982\u5ff5\uff0c\u53ef\u4ee5\u7528\u6765\u8c03\u67e5\u66f4\u52a0\u5e95\u5c42\u7684\u7f51\u7edc\u95ee\u9898\u3002\u4f8b\u5982\uff1a\nping 1.1.1.1 \u5982\u679c\u80fd\u591f ping \u901a\uff0c\u90a3\u4e48\u8bf7\u547c\u53eb\u7f51\u7edc\u5de5\u7a0b\u5e08\uff0c\u544a\u8bc9\u4ed6\u4eec\u300c\u80fd ping \u901a\u67d0\u67d0\u5730\u5740\uff0c\u4f46\u65e0\u6cd5 telnet \u67d0\u67d0\u5730\u5740\u67d0\u67d0\u7aef\u53e3\u300d\uff0c\u5e76\u9644\u4e0a telnet \u7684\u539f\u59cb\u8f93\u51fa\u3002\u4ed6\u4eec\u53ef\u80fd\u4f1a\u68c0\u67e5\u7f51\u5173\u4e0a\u7684 iptables \u662f\u5426\u914d\u7f6e\u6b63\u786e\uff0c\u8bf4\u4e0d\u5b9a\u4f60\u7684 TCP \u6570\u636e\u5305\u88ab\u76f4\u63a5 DROP \u6389\uff0c\u6216\u8005\u91cd\u5b9a\u5411\u5230\u67d0\u4e2a\u300c\u9ed1\u6d1e\u300d\u91cc\u4e86\u3002\n\u5982\u679c ping \u4e0d\u901a\uff0c\u6709\u4e24\u5927\u53ef\u80fd\u7684\u539f\u56e0\uff1a\n IP \u6216\u7f51\u5173\u914d\u7f6e\u6709\u8bef\u3002 \u5728\u4f60\u672c\u5730\u5230\u76ee\u6807\u5730\u5740\u7684\u9014\u4e2d\uff0c\u67d0\u4e2a\u7f51\u5173\u51fa\u73b0\u4e86\u6545\u969c\uff0c\u6216\u662f\u8def\u7531\u89c4\u5219\u914d\u7f6e\u9519\u8bef\uff0c\u6216\u662f\u88ab\u9632\u706b\u5899\u62e6\u622a\u3002  \u7b2c\u4e00\u79cd\u60c5\u51b5\uff0c\u4e00\u822c\u5728 telnet \u7684\u65f6\u5019\u5c31\u4f1a\u62a5\u9519\u3002\u6bd4\u5982 ping \u63d0\u793a No route to host\uff0c\u5bf9\u4e8e\u8fd0\u884c\u5728 TCP \u5c42\u7684 telnet \u6765\u8bf4\uff0c\u9519\u8bef\u4fe1\u606f\u5c31\u662f Network is unreachable\u3002\n\u7b2c\u4e8c\u79cd\u60c5\u51b5\uff0c\u63a8\u8350\u4f7f\u7528 mtr \u5de5\u5177\uff0c\u4f8b\u5982\uff1a\nsudo mtr -b 1.1.1.1 mtr \u5c06\u4f1a\u8ffd\u8e2a ICMP \u6570\u636e\u5305\u7684\u8def\u5f84\uff0c\u5e76\u6301\u7eed\u5411\u8fd9\u4e9b\u7f51\u5173\u53d1\u51fa ping \u8bf7\u6c42\u3002\u6837\u4f8b\u8f93\u51fa\u5982\u4e0b\uff1a\nMy traceroute [vUNKNOWN] Suns-Laptop.local (172.20.10.2) 2019-05-25T09:26:06+0800 Keys: Help Display mode Restart statistics Order of fields quit Packets Pings Host Loss% Snt Last Avg Best Wrst StDev 1. bogon (172.20.10.1) 0.0% 5 36.0 15.6 3.3 36.0 14.6 2. ??? 3. bogon (10.255.255.97) 0.0% 5 50.5 49.7 44.3 56.8 4.6 4. ??? 5. 115.170.139.241 (115.170.139.241) 0.0% 5 87.2 67.5 48.0 101.7 25.2 6. 36.112.252.5 (36.112.252.5) 0.0% 5 46.5 63.2 46.5 107.9 25.2 7. 202.97.94.230 (202.97.94.230) 0.0% 5 80.8 128.3 80.8 171.5 43.9 8. 202.97.85.58 (202.97.85.58) 0.0% 5 72.0 60.9 53.6 72.0 8.3 9. 202.97.90.238 (202.97.90.238) 0.0% 5 358.0 326.4 312.2 358.0 21.6 10. 202.97.50.22 (202.97.50.22) 0.0% 5 336.9 336.1 323.5 342.3 8.8 11. 218.30.54.214 (218.30.54.214) 0.0% 4 228.7 227.6 217.7 243.9 11.9 12. one.one.one.one (1.1.1.1) 0.0% 4 311.5 288.4 247.4 322.2 34.7 \u9996\u5148\uff0c\u8bf7\u786e\u8ba4\u6700\u540e\u4e00\u884c\u662f\u4f60\u7684\u76ee\u6807\u5730\u5740\uff0c\u5982\u679c\u4e0d\u662f\uff0c\u90a3\u4e48\u6700\u540e\u4e00\u884c\u5f88\u6709\u53ef\u80fd\u5c31\u662f\u51fa\u95ee\u9898\u7684\u7f51\u5173\u3002\n\u53e6\u5916\u6ce8\u610f Loss% \u4e00\u5217\uff0c\u5982\u679c\u67d0\u4e2a\u7f51\u5173\u4e22\u5305\u7387\u5f88\u9ad8\uff0c\u90a3\u4e48\u5b83\u53ef\u80fd\u4e5f\u5b58\u5728\u95ee\u9898\u3002\nmtr \u7684\u4fe1\u606f\u901a\u5e38\u6765\u8bf4\u4e0d\u9700\u8981\u5f00\u53d1\u8005\u5206\u6790\uff0c\u53ea\u9700\u539f\u5c01\u4e0d\u52a8\u5730\u628a\u8f93\u51fa\u53d1\u7ed9\u7f51\u7edc\u5de5\u7a0b\u5e08\u5373\u53ef\uff0c\u4ed6\u4eec\u4f1a\u8bfb\u61c2\u7684\u3002\nARP \u534f\u8bae \u4e0a\u6587\u4e2d\u63d0\u5230\u7684\u65b9\u6cd5\u5bf9\u4e8e\u666e\u901a\u7f51\u7edc\u7528\u6237\u5df2\u7ecf\u975e\u5e38\u5e95\u5c42\u4e86\uff0c\u5982\u679c\u4f60\u6709\u5174\u8da3\uff0c\u4e5f\u53ef\u4ee5\u770b\u770b\u8fd9\u4e00\u5c0f\u8282\u3002\n\u5982\u679c mtr \u7684\u8f93\u51fa\u7c7b\u4f3c\u8fd9\u6837\uff1a\n Packets Pings Host Loss% Snt Last Avg Best Wrst StDev 1. bogon (172.20.10.1) 100.0% 5 ... \u8fd9\u610f\u5473\u7740\u4f60\u7535\u8111\u7684\u7f51\u5173\uff08\u901a\u5e38\u662f\u8def\u7531\u5668\uff09\u90fd ping \u4e0d\u901a\u3002\u5728 IP \u548c\u7f51\u5173\u786e\u8ba4\u914d\u7f6e\u65e0\u8bef\u7684\u60c5\u51b5\u4e0b\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 arp-scan \u5de5\u5177\u5411\u672c\u5730\u7f51\u7edc\u4e3b\u52a8\u53d1\u51fa ARP \u8bf7\u6c42\uff0c\u4f8b\u5982\uff1a\narp-scan 172.20.10.1\/24 \u5176\u4e2d\uff0c172.20.10.1\/24 \u662f\u7f51\u5173 IP + \u5b50\u7f51\u63a9\u7801\u8f6c\u6362\u6210 CIDR \u7684\u5f62\u5f0f\u3002\u901a\u5e38\u6765\u8bf4\uff0c\u6211\u4eec\u53ea\u9700\u4f7f\u7528 \u7f51\u5173IP\/24 \u5373\u53ef\uff0c\/24 \u8868\u793a\u5b50\u7f51\u63a9\u7801\u4e3a 255.255.255.0\u3002\n\u5982\u679c\u7f51\u5173\u6b63\u5e38\u54cd\u5e94\u4e86 ARP \u8bf7\u6c42\uff0c\u8f93\u51fa\u5e94\u5f53\u7c7b\u4f3c\u4e8e\uff1a\nInterface: en0, datalink type: EN10MB (Ethernet) WARNING: host part of 172.20.10.1\/24 is non-zero Starting arp-scan 1.9.5 with 256 hosts (https:\/\/github.com\/royhills\/arp-scan) 172.20.10.1 fe:2a:9c:ee:16:64 (Unknown) 619 packets received by filter, 0 packets dropped by kernel Ending arp-scan 1.9.5: 256 hosts scanned in 1.866 seconds (137.19 hosts\/sec). 1 responded ping \u4e0d\u901a\u7f51\u5173\uff08\u4f8b\u5982 No route to host\uff09\uff0c\u4f46\u662f\u7f51\u7edc\u8bbe\u5907\u6b63\u5e38\u54cd\u5e94\u4e86 ARP \u8bf7\u6c42\uff1b\u9664\u9632\u706b\u5899\u5916\uff0c\u6211\u80fd\u60f3\u5230\u7684\u552f\u4e00\u53ef\u80fd\u6027\uff0c\u5c31\u662f\u4f60\u7684\u7535\u8111\u8fd8\u6ca1\u6709 IP \u5730\u5740\u3002\n\u5c0f\u7ed3 \u53ef\u4ee5\u770b\u51fa\uff0c\u672c\u6587\u6240\u8ff0\u6392\u67e5\u987a\u5e8f\u4ece\u8fd0\u884c\u5728\u4e03\u5c42\u7684 HTTP \u534f\u8bae\uff0c\u5230\u8fd0\u884c\u5728\u4e8c\u5c42\u7684 ARP \u534f\u8bae\uff0c\u9010\u6e10\u6df1\u5165\u3002\n\u6700\u540e\uff0c\u6211\u4e0d\u662f\u7f51\u7edc\u5de5\u7a0b\u4e13\u4e1a\u51fa\u8eab\uff0c\u672c\u6587\u6216\u8bb8\u8fd8\u4e0d\u591f\u300c\u4e13\u4e1a\u300d\u3002\u5982\u679c\u4f60\u53d1\u73b0\u4efb\u4f55\u9519\u8bef\u3001\u7591\u95ee\uff0c\u6216\u662f\u66f4\u597d\u7684\u65b9\u6848\u3001\u66f4\u591a\u7684\u573a\u666f\uff0c\u6b22\u8fce\u7559\u8a00\u8865\u5145\u3002\n\u94fe\u8def\u5c42 \u6700\u540e\u7684\u6700\u540e\u3002\n\u5982\u679c ARP \u534f\u8bae\u90fd\u4e0d\u80fd\u6b63\u5e38\u5de5\u4f5c\u3002\n\u90a3\u4e48\u4f60\u5bfb\u6c42\u5e2e\u52a9\u7684\u5bf9\u8c61\uff0c\u4e5f\u8bb8\u4e0d\u662f\u7f51\u7edc\u5de5\u7a0b\u5e08\u4e86\u3002\u4f60\u53ef\u80fd\u9700\u8981\u53eb\u786c\u4ef6\u5927\u4f6c\u6765\u68c0\u67e5\u4e00\u4e0b\uff1a\n \u4f60\u7535\u8111\u7684\u65e0\u7ebf\u7f51\u5361\u662f\u5426\u6b63\u5e38\u5de5\u4f5c \u5468\u56f4\u65e0\u7ebf\u7535\u73af\u5883\u662f\u5426\u5b58\u5728\u5e72\u6270 \u67d0\u6b21\u7535\u95ea\u96f7\u9e23\u662f\u5426\u51fb\u4e2d\u4e86\u4e8c\u5c42\u4ea4\u6362\u673a \u4ee5\u53ca\u7f51\u7ebf\u662f\u5426\u88ab\u8001\u9f20\u54ac\u4e86\u3002 ","permalink":"https:\/\/wi1dcard.dev\/posts\/inspect-network-failure-like-a-pro\/","summary":"<p>\u4ece\u4e8b\u8fd0\u7ef4\u5de5\u7a0b\u5e08\uff08\u517c\u516c\u53f8\u7f51\u7ba1\ud83d\ude02\uff09\u4ee5\u6765\uff0c\u9047\u5230\u4e0d\u5c11\u5404\u5f0f\u5404\u6837\u7684\u7f51\u7edc\u6545\u969c\uff0c\u6709\u7684\u6765\u81ea\u4e8e\u8def\u7531\u5668\u95ee\u9898\uff0c\u6709\u7684\u5219\u662f\u5ba2\u6237\u7aef\u914d\u7f6e\u9519\u8bef\u3002\u800c\u5f00\u53d1\u4eba\u5458\u7684\u53cd\u9988\u5927\u591a\u7c7b\u4f3c\u4e8e\uff1a<\/p>\n<ul>\n<li>\u300c\u6211\u4e0a\u4e0d\u4e86\u7f51\u4e86\uff01\u300d<\/li>\n<li>\u300c\u7f51\u7edc\u5361\u4e86\u5417\uff1f\u4e00\u76f4\u5728\u52a0\u8f7d&hellip;\u300d<\/li>\n<\/ul>","title":"\u5982\u4f55\u4e13\u4e1a\u5730\u8868\u8fbe\u300c\u6211\u4e0a\u4e0d\u4e86\u7f51\u4e86\uff01\u300d"},{"content":"\u6700\u8fd1\u6298\u817e\u79d1\u5b66\u4e0a\u7f51\u7f51\u5173\uff0c\u535a\u5ba2\u505c\u66f4\u4e00\u6bb5\u65f6\u95f4\uff1b\u968f\u624b\u8bb0\u5f55\u4e00\u6bb5\u5c0f\u811a\u672c\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u7528\u3002\u8fd9\u662f\u76ee\u524d\u6211\u627e\u5230\u7684\u6700\u7b80\u3001\u6700\u901a\u7528\u65b9\u6848\uff0c\u53ea\u9700 ip \u548c grep \u547d\u4ee4\u5373\u53ef\u3002\nCIDR=$(ip -f inet addr show dev eth0 | grep -Pom1 &#39;inet \\K[\\d.\/]+&#39;) GATEWAY=$(ip -f inet route show default dev eth0 | grep -Pom1 &#39;via \\K[\\d.]+&#39;) \u5176\u4e2d\uff0ceth0 \u8bf7\u66ff\u6362\u4e3a\u6307\u5b9a\u63a5\u53e3\u540d\u79f0\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/gather-gateway-ip-and-cidr\/","summary":"<p>\u6700\u8fd1\u6298\u817e\u79d1\u5b66\u4e0a\u7f51\u7f51\u5173\uff0c\u535a\u5ba2\u505c\u66f4\u4e00\u6bb5\u65f6\u95f4\uff1b\u968f\u624b\u8bb0\u5f55\u4e00\u6bb5\u5c0f\u811a\u672c\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u7528\u3002\u8fd9\u662f\u76ee\u524d\u6211\u627e\u5230\u7684\u6700\u7b80\u3001\u6700\u901a\u7528\u65b9\u6848\uff0c\u53ea\u9700 <code>ip<\/code> \u548c <code>grep<\/code> \u547d\u4ee4\u5373\u53ef\u3002<\/p>","title":"\u5728 Linux \u4e2d\u83b7\u53d6\u9ed8\u8ba4\u7f51\u5173\u548c CIDR"},{"content":"\u5728\u65e9\u671f \u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528 \u8bfe\u7a0b\u5f00\u59cb\u7f16\u5199\u4e4b\u524d\uff0c\u5c31\u8003\u8651\u5230\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u95ee\u9898\uff1a\u5982\u4f55\u4fdd\u8bc1 Laravel-China \u4e0a\u53d1\u5e03\u7684\u6587\u7ae0\u4e0e GitHub \u4ed3\u5e93\u5185\u7684 Markdown \u6e90\u6587\u4ef6\u4fdd\u6301\u540c\u6b65\uff1f\n\u95ee\u9898 \u6700\u539f\u59cb\u7684\u529e\u6cd5\u662f\u6bcf\u6b21\u66f4\u65b0\u540e -&gt; \u627e\u5230\u5bf9\u5e94\u6587\u7ae0\u7684 URL -&gt; \u5728\u7f51\u7ad9\u4e0a\u4f5c\u51fa\u540c\u6837\u7684\u4fee\u6539\u3002\n\u4f46\u8fd9\u4e2a\u60f3\u6cd5\u5f88\u5feb\u5c31\u88ab\u6253\u6d88\u4e86\u3002\u539f\u56e0\u5f88\u591a\uff1a\n \u7eaf\u624b\u5de5\uff0c\u5bb9\u6613\u4ea7\u751f\u64cd\u4f5c\u5931\u8bef\u3002 \u8d39\u65f6\u8d39\u529b\u7684\u91cd\u590d\u6027\u65e0\u610f\u4e49\u5de5\u4f5c\uff0c\u803d\u6401\u4e3b\u8981\u751f\u4ea7\u529b\uff08\u7f16\u5199\u5185\u5bb9\uff09\u7684\u8f93\u51fa\u3002 \u61d2\u3002  \u54b3\u54b3\u3002\n\u6548\u679c\u4e00\u89c8 \u6700\u7ec8\u51b3\u5b9a\u5b8c\u5168\u81ea\u52a8\u5316\uff0c\u529b\u4e89\u4e00\u52b3\u6c38\u9038\u3002\u7ecf\u8fc7\u4e00\u6bb5\u65f6\u95f4\u6298\u817e\uff0c\u76ee\u524d\u6548\u679c\u5982\u4e0b\uff1a\n\u601d\u8def \u7ed3\u5408\u81ea\u5df1\u591a\u5e74\u524d\u7684\u6293\u5305\u5206\u6790\u6280\u80fd\u4ee5\u53ca\u5982\u4eca\u7684 CI \u6280\u80fd\uff0c\u57fa\u672c\u601d\u8def\u4e3a\uff1a\n \u4f5c\u51fa\u53d8\u66f4\uff0cgit commit + git push GitHub \u901a\u77e5 Travis CI Travis CI \u6267\u884c\u6301\u7eed\u4ea4\u4ed8\u6d41\u7a0b  \u98ce\u683c\u68c0\u67e5 \u53d1\u5e03\u6587\u7ae0    \u901a\u8fc7\u4ee5\u4e0a\u7684\u53d1\u5e03\u6d41\u7a0b\uff0c\u4e0d\u4ec5\u53ef\u4ee5\u8fbe\u5230\u8d8b\u8fd1\u5b9e\u65f6\u7684\u6587\u7ae0\u66f4\u65b0\uff0c\u8fd8\u80fd\u591f\u89e3\u51b3\u4ee5\u4e0b\u95ee\u9898\uff1a\n \u53d1\u5e03\u524d\u786e\u4fdd\u884c\u6587\u89c4\u8303\uff0c\u5305\u62ec\u6807\u70b9\u4f7f\u7528\u65e0\u8bef\u3001\u4e2d\u82f1\u6587\u4e4b\u95f4\u7a7a\u683c\u7b49\uff1b\u63a5\u5230 PR \u65f6\u4e5f\u80fd\u81ea\u52a8\u68c0\u67e5\uff0c\u65b9\u4fbf\u793e\u533a\u8d21\u732e\u3002 \u53d1\u5e03\u524d\u5bf9\u5185\u5bb9\u9884\u5904\u7406\uff0c\u4f8b\u5982\u53bb\u6389\u5185\u5bb9\u4e2d\u7684\u4e00\u7ea7\u6807\u9898\uff0c\u63d2\u5165\u56fa\u5b9a\u7b80\u4ecb\u3001\u76ee\u5f55\u7b49\u3002  \u524d 2 \u6b65\u4e2d GitHub + Travis \u7684\u76f8\u5173\u6587\u7ae0\u6709\u5f88\u591a\uff0c\u6bd4\u5982 \u8fd9\u7bc7\u535a\u5ba2\uff0c\u5728\u6b64\u6682\u4e0d\u8be6\u8ff0\uff1b\u63a5\u4e0b\u6765\u6211\u5c06\u91cd\u70b9\u5206\u6790\u7b2c 3 \u6b65\u7684\u6d41\u7a0b\u3002\n\u98ce\u683c\u68c0\u67e5 \u6211\u4f7f\u7528 \u8fd9\u7bc7\u535a\u6587 \u4e2d\u4ecb\u7ecd\u7684 Lint-md \u9879\u76ee\u5b9e\u73b0\u3002\u4e3a\u4e86\u65b9\u4fbf CI \u4f7f\u7528\uff0c\u6211\u8fd8\u7279\u610f\u63d0\u4ea4\u4e86\u4e00\u4e2a Pull Request\uff0c\u7528\u4e8e\u652f\u6301 Docker \u955c\u50cf\u3002\n\u5177\u4f53\u4ee3\u7801\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u6709\u4e00\u884c\u3002\u4f60\u53ef\u4ee5\u5728 \u8fd9\u91cc \u627e\u5230\uff1a\ndocker run --rm -v $dir:\/data yuque\/lint-md lint-md -c \/data\/lint-md.json \/data\/src \u719f\u6089 Docker \u7684\u8bdd\u5f88\u5bb9\u6613\u8bfb\u61c2\uff1b\u82e5\u662f\u4e0d\u719f\u6089\uff0c\u4f60\u53ef\u4ee5\u9605\u8bfb \u8fd9\u7bc7\u6587\u7ae0\u3002\n\u5176\u4e2d\uff0c$dir \u662f\u9879\u76ee\u6839\u76ee\u5f55\uff0clint-md -c \/data\/lint-md.json \/data\/src \u4fbf\u662f\u666e\u901a\u7684 Lint-md \u4f7f\u7528\u65b9\u6cd5\u3002\n\u53d1\u5e03\u6587\u7ae0 \u6574\u5957\u53d1\u5e03\u7684\u6d41\u7a0b\u6bd4\u8f83\u590d\u6742\uff0c\u53ef\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5c0f\u6b65\u9aa4\uff1a\n \u4f7f\u7528\u957f\u671f Cookies \u6362\u53d6\u4e34\u65f6 Cookies \u83b7\u5f97 CSRF Token \u62c9\u53d6\u5df2\u53d1\u5e03\u7684\u6587\u7ae0\u5217\u8868 \u904d\u5386\u672c\u5730 Markdown \u6e90\u6587\u4ef6\u5217\u8868 \u6839\u636e\u672c\u5730\u6587\u4ef6\u540d\u89e3\u6790\u6587\u7ae0\u6807\u9898 \u68c0\u7d22\u662f\u5426\u5df2\u53d1\u5e03\uff0c\u5e76\u53d6\u5f97\u6587\u7ae0 ID \u9884\u5904\u7406\u6587\u7ae0\u5185\u5bb9\uff08\u63d2\u5165\u7b80\u4ecb\u3001\u62fc\u63a5\u5b8c\u6574\u6807\u9898\uff09 \u5c06\u6700\u7ec8\u5185\u5bb9\u53d1\u5e03\uff08\u521b\u5efa\u6216\u66f4\u65b0\uff09 \u5faa\u73af\u6267\u884c 5 - 8 \u76f4\u5230\u904d\u5386\u5b8c\u6210  \u5176\u4e2d\uff0c\u4f7f\u7528\u7c97\u4f53\u6807\u6ce8\u7684 1\u30012\u30013\u30018\uff0c\u9700\u8981\u4e0e\u670d\u52a1\u5668\u8fdb\u884c\u901a\u8baf\uff1b\u4e0d\u8fc7\u6211\u6ca1\u6709 Laravel-China \u7684\u63a5\u53e3\uff0c\u4e5f\u4e0d\u597d\u610f\u601d\u9ebb\u70e6 @Summer\u3002\u6240\u4ee5\u5e72\u8106\u81ea\u5df1\u52a8\u624b\uff0c\u4e30\u8863\u8db3\u98df \u2014\u2014 \u5229\u7528 Chrome Developer Tool \u7684 Network \u529f\u80fd\u5feb\u901f\u6293\u5305\uff0c\u5206\u6790\u6574\u7406\u540e\u4f7f\u7528 PHP \u5b9e\u73b0\u4e00\u6b3e\u5c0f\u5de5\u5177\uff0c\u540d\u4e3a learnku-deploy-bot\uff0c\u6211\u6682\u65f6\u79f0\u5b83\u4e3a\u300c\u90e8\u7f72\u673a\u5668\u4eba\u300d\u3002\n\u8fd9\u4e2a\u673a\u5668\u4eba\u53ef\u62c6\u5206\u4e3a\u4e09\u5927\u90e8\u5206\uff0c\u4f60\u53ef\u4ee5 Git Clone \u6e90\u7801\u540e\u67e5\u770b src \u76ee\u5f55\uff1a\n Requests\uff1a\u5305\u542b\u6240\u6709\u7684 HTTP \u8bf7\u6c42\u5b9a\u4e49\uff0c\u57fa\u4e8e Buzz\uff08\u4e00\u4e2a\u517c\u5bb9 PSR-7\u3001PSR-17\u3001PSR-18 \u7684 HTTP \u5ba2\u6237\u7aef\uff09\u5b9e\u73b0\uff0c\u4f60\u53ef\u4ee5\u7406\u89e3\u4e3a MVC \u4e2d\u7684 Models\u3002 Extractors\uff1a\u5305\u542b\u6240\u6709\u7684\u8bf7\u6c42\u89e3\u6790\u5668\uff0c\u5229\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u7b49\u5b57\u7b26\u4e32\u5904\u7406\u65b9\u5f0f\u63d0\u53d6\u6587\u672c\uff1b\u4f60\u53ef\u4ee5\u7406\u89e3\u4e3a MVC \u4e2d\u7684 Views\u3002 Commands\uff1a\u5305\u542b\u6240\u6709\u7684 CLI \u547d\u4ee4\uff0c\u57fa\u4e8e Symfony \u7684 Console \u6269\u5c55\u5305\u5b9e\u73b0\uff1b\u5728\u8fd9\u91cc\u5b9e\u4f8b\u5316\u5e76\u53d1\u9001 Requests\uff0c\u518d\u4ea4\u7ed9 Extractors \u63d0\u53d6\u9700\u8981\u7684\u6570\u636e\u3002\u4f60\u53ef\u4ee5\u7406\u89e3\u4e3a MVC \u4e2d\u7684 Controllers\u3002  \u5bf9\u4e8e\u7528\u6237\uff08\u6211\u81ea\u5df1\ud83d\ude02\uff09\u6765\u8bf4\uff0c\u53ea\u9700\u5173\u5fc3\u516c\u5f00\u7684 Commands \u5373\u53ef\uff0c\u4f8b\u5982\u9a8c\u8bc1 Session \u7684 session\uff0c\u66f4\u65b0\u6587\u7ae0\u7684 article:update\uff1b\u6570\u636e\u6e90 Requests \u548c Extractors \u7531 Commands \u8fdb\u884c\u7edf\u4e00\u8c03\u914d\u3002\n \u7531\u4e8e\u662f\u4e2a\u4eba\u4f7f\u7528\u7684\u5c0f\u5de5\u5177\uff0c\u6240\u4ee5\u8bbe\u8ba1\u6bd4\u8f83\u7b80\u964b\uff0c\u8bb8\u591a\u5730\u65b9\u5e76\u4e0d\u5b8c\u5584\uff0c\u5efa\u8bae\u4ec5\u4f5c\u5b66\u4e60\u4f7f\u7528\u3002\n \u4e3a\u4e86\u63d0\u9ad8\u53ef\u590d\u7528\u6027\uff0clearnku-deploy-bot \u5e76\u6ca1\u6709\u4e0e\u8bfe\u7a0b\u6709\u4efb\u4f55\u76f4\u63a5\u7684\u5173\u7cfb\uff1b\u4f60\u53ef\u4ee5\u628a\u5b83\u7406\u89e3\u4e3a\u4e00\u4e2a\u901a\u7528\u7684 Laravel-China CLI \u5ba2\u6237\u7aef\u3002\n\u81f3\u4e8e\u5269\u4e0b\u7684 4\u30015\u30016\u30017\u30019\uff0c\u4e5f\u5c31\u662f\u548c\u8bfe\u7a0b\u76f4\u63a5\u76f8\u5173\u7684\u53d1\u5e03\u6d41\u7a0b\uff0c\u662f\u4f7f\u7528 Bash \u811a\u672c\u5b9e\u73b0\uff0c\u6e90\u7801 \u4e0e\u8bfe\u7a0b\u6587\u4ef6\u4f4d\u4e8e\u540c\u4e00\u4ed3\u5e93\uff1b\u901a\u8fc7\u8be5\u811a\u672c\u904d\u5386\u6587\u7ae0\uff0c\u5e76\u8c03\u7528\u90e8\u7f72\u673a\u5668\u4eba\u63d0\u4f9b\u7684 Commands\uff0c\u5b8c\u6210\u7edf\u4e00\u7684\u8bfe\u7a0b\u53d1\u5e03\u5de5\u4f5c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/automatic-learnku-deploy-bot\/","summary":"<p>\u5728\u65e9\u671f <a href=\"https:\/\/github.com\/wi1dcard\/laravel-deployment\" target=\"_blank\">\u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528<\/a> \u8bfe\u7a0b\u5f00\u59cb\u7f16\u5199\u4e4b\u524d\uff0c\u5c31\u8003\u8651\u5230\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u95ee\u9898\uff1a<strong>\u5982\u4f55\u4fdd\u8bc1 Laravel-China \u4e0a\u53d1\u5e03\u7684\u6587\u7ae0\u4e0e GitHub \u4ed3\u5e93\u5185\u7684 Markdown \u6e90\u6587\u4ef6\u4fdd\u6301\u540c\u6b65<\/strong>\uff1f<\/p>","title":"\u6211\u5982\u4f55\u5b9e\u73b0 Laravel-China \u5168\u81ea\u52a8\u7cfb\u5217\u6587\u7ae0\u53d1\u5e03"},{"content":"\u4ee5 Laravel 5.8 \u6587\u6863 \u4e3a\u51c6\uff0c\u6d45\u6790 Nginx \u914d\u7f6e\u3002\u53ef\u4f5c\u4e3a \u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528 \u7684\u62d3\u5c55\u9605\u8bfb\u3002\n\u65b9\u4fbf\u8d77\u89c1\uff0c\u6211\u5728\u6ce8\u91ca\u4e2d\u4f7f\u7528 [] \u5305\u88f9\u5f15\u7528\u914d\u7f6e\u4e2d\u7684\u503c\u3002\nserver { # \u76d1\u542c HTTP \u534f\u8bae\u9ed8\u8ba4\u7684 [80] \u7aef\u53e3\u3002  listen 80; # \u7ed1\u5b9a\u4e3b\u673a\u540d [example.com]\u3002  server_name example.com; # \u670d\u52a1\u5668\u7ad9\u70b9\u6839\u76ee\u5f55 [\/example.com\/public]\u3002  root \/example.com\/public; # \u6dfb\u52a0\u51e0\u6761\u6709\u5173\u5b89\u5168\u7684\u54cd\u5e94\u5934\uff1b\u4e0e Google+ \u7684\u914d\u7f6e\u7c7b\u4f3c\uff0c\u8be6\u60c5\u53c2\u89c1\u6587\u672b\u3002  add_header X-Frame-Options &#34;SAMEORIGIN&#34;; add_header X-XSS-Protection &#34;1; mode=block&#34;; add_header X-Content-Type-Options &#34;nosniff&#34;; # \u7ad9\u70b9\u9ed8\u8ba4\u9875\u9762\uff1b\u53ef\u6307\u5b9a\u591a\u4e2a\uff0c\u5c06\u987a\u5e8f\u67e5\u627e\u3002  # \u4f8b\u5982\uff0c\u8bbf\u95ee http:\/\/example.com\/ Nginx \u5c06\u9996\u5148\u5c1d\u8bd5\u300c\u7ad9\u70b9\u6839\u76ee\u5f55\/index.html\u300d\u662f\u5426\u5b58\u5728\uff0c\u4e0d\u5b58\u5728\u5219\u7ee7\u7eed\u5c1d\u8bd5\u300c\u7ad9\u70b9\u6839\u76ee\u5f55\/index.htm\u300d\uff0c\u4ee5\u6b64\u7c7b\u63a8...  index index.html index.htm index.php; # \u6307\u5b9a\u5b57\u7b26\u96c6\u4e3a UTF-8  charset utf-8; # Laravel \u9ed8\u8ba4\u91cd\u5199\u89c4\u5219\uff1b\u5220\u9664\u5c06\u5bfc\u81f4 Laravel \u8def\u7531\u5931\u6548\u4e14 Nginx \u54cd\u5e94 404\u3002  location \/ { try_files $uri $uri\/ \/index.php?$query_string; } # \u5173\u95ed [\/favicon.ico] \u548c [\/robots.txt] \u7684\u8bbf\u95ee\u65e5\u5fd7\u3002  # \u5e76\u4e14\u5373\u4f7f\u5b83\u4eec\u4e0d\u5b58\u5728\uff0c\u4e5f\u4e0d\u5199\u5165\u9519\u8bef\u65e5\u5fd7\u3002  location = \/favicon.ico { access_log off; log_not_found off; } location = \/robots.txt { access_log off; log_not_found off; } # \u5c06 [404] \u9519\u8bef\u4ea4\u7ed9 [\/index.php] \u5904\u7406\uff0c\u8868\u793a\u7531 Laravel \u6e32\u67d3\u7f8e\u89c2\u7684\u9519\u8bef\u9875\u9762\u3002  error_page 404 \/index.php; # URI \u7b26\u5408\u6b63\u5219\u8868\u8fbe\u5f0f [\\.php$] \u7684\u8bf7\u6c42\u5c06\u8fdb\u5165\u6b64\u6bb5\u914d\u7f6e  location ~ \\.php$ { # \u914d\u7f6e FastCGI \u670d\u52a1\u5730\u5740\uff0c\u53ef\u4ee5\u4e3a IP:\u7aef\u53e3\uff0c\u4e5f\u53ef\u4ee5\u4e3a Unix socket\u3002  fastcgi_pass unix:\/var\/run\/php\/php7.2-fpm.sock; # \u914d\u7f6e FastCGI \u7684\u4e3b\u9875\u4e3a index.php\u3002  fastcgi_index index.php; # \u914d\u7f6e FastCGI \u53c2\u6570 SCRIPT_FILENAME \u4e3a $realpath_root$fastcgi_script_name\u3002  fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; # \u5f15\u7528\u66f4\u591a\u9ed8\u8ba4\u7684 FastCGI \u53c2\u6570\u3002  include fastcgi_params; } # \u901a\u4fd7\u5730\u8bf4\uff0c\u4ee5\u4e0a\u914d\u7f6e\u5c06\u6240\u6709 URI \u4ee5 .php \u7ed3\u5c3e\u7684\u8bf7\u6c42\uff0c\u5168\u90e8\u4ea4\u7ed9 PHP-FPM \u5904\u7406\u3002  # \u9664\u7b26\u5408\u6b63\u5219\u8868\u8fbe\u5f0f [\/\\.(?!well-known).*] \u4e4b\u5916\u7684 URI\uff0c\u5168\u90e8\u62d2\u7edd\u8bbf\u95ee  # \u4e5f\u5c31\u662f\u8bf4\uff0c\u62d2\u7edd\u516c\u5f00\u4ee5 [.] \u5f00\u5934\u7684\u76ee\u5f55\uff0c[.well-known] \u9664\u5916  location ~ \/\\.(?!well-known).* { deny all; } } \u5173\u4e8e X-Frame-Options\u3001X-XSS-Protection \u548c X-Content-Type-Options \u53ef\u53c2\u8003 \u8fd9\u7bc7\u6587\u7ae0\uff0c\u81ea\u8ba4\u4e3a\u4f5c\u8005\u8bb2\u5f97\u8fd8\u4e0d\u9519\uff0c\u901a\u4fd7\u6613\u61c2\u5e76\u4e14\u662f\u4e2d\u6587\u3002\n\u5173\u4e8e .well-known \u76ee\u5f55\u7684\u8be6\u7ec6\u89e3\u91ca\uff0c\u53ef\u53c2\u8003 \u8fd9\u7bc7\u95ee\u7b54\uff08\u82f1\u6587\uff09\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-recommended-nginx-conf-analysis\/","summary":"<p>\u4ee5 <a href=\"https:\/\/laravel.com\/docs\/5.8\/deployment#server-configuration\" target=\"_blank\">Laravel 5.8 \u6587\u6863<\/a> \u4e3a\u51c6\uff0c\u6d45\u6790 Nginx \u914d\u7f6e\u3002\u53ef\u4f5c\u4e3a <a href=\"https:\/\/github.com\/wi1dcard\/laravel-deployment\" target=\"_blank\">\u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528<\/a> \u7684\u62d3\u5c55\u9605\u8bfb\u3002<\/p>","title":"\u6d45\u6790 Laravel \u6587\u6863\u63a8\u8350\u7684 Nginx \u914d\u7f6e"},{"content":"\u535a\u5ba2\u53c8\u8df3\u7968\u4e00\u9635\u5b50\uff0c\u4e0d\u8fc7\u6700\u8fd1\u5e76\u6ca1\u6709\u95f2\u7740\uff0c\u800c\u662f\u628a\u4e1a\u4f59\u65f6\u95f4\u5168\u90e8\u6295\u5165\u5230\u4e86 Laravel \u90e8\u7f72\u8bfe\u7a0b\u3002\u5728\u5199\u4f5c\u65f6\u7ecf\u5e38\u9700\u8981\u5bf9\u7a97\u53e3\u622a\u56fe\uff0c\u4e3a\u4e86\u63d0\u9ad8\u9605\u8bfb\u4f53\u9a8c\uff0c\u9700\u786e\u4fdd\u622a\u56fe\u5927\u5c0f\u7edf\u4e00\uff1b\u56e0\u6b64\u5982\u4f55\u8ba9\u7a97\u53e3 \u5feb\u901f \u5730\u7f29\u653e\u4e3a\u6307\u5b9a\u50cf\u7d20\u7684 \u7cbe\u786e \u5927\u5c0f\uff0c\u6210\u4e86\u4e00\u4e2a\u4e0d\u53ef\u6216\u7f3a\u7684\u9700\u6c42\u3002\n\u7ecf\u8fc7\u4e00\u756a\u8c37\u6b4c\uff0c\u53d1\u73b0\u4ee5\u4e0b\u89e3\u51b3\u65b9\u6848\uff1a\n(* This Apple script will resize any program window to an exact size and the window is then moved to the center of your screen. Specify the program name, height and width below and run the script. Written by Amit Agarwal on December 10, 2013 *) set theApp to &quot;Google Chrome&quot; set appHeight to 600 set appWidth to 1000 tell application &quot;Finder&quot; set screenResolution to bounds of window of desktop end tell set screenWidth to item 3 of screenResolution set screenHeight to item 4 of screenResolution tell application theApp activate reopen set yAxis to (screenHeight - appHeight) \/ 2 as integer set xAxis to (screenWidth - appWidth) \/ 2 as integer set the bounds of the first window to {xAxis, yAxis, appWidth + xAxis, appHeight + yAxis} end tell \u6e90\u4ee3\u7801\u4fee\u6539\u81ea\uff1ahttps:\/\/www.labnol.org\/software\/resize-mac-windows-to-specific-size\/28345\/\u3002\n\u5176\u4e2d\uff1a\n &quot;Google Chrome&quot; \u8bf7\u66ff\u6362\u4e3a\u5b9e\u9645\u7684\u5e94\u7528\u540d\u3002 600 \u4e0e 1000 \u5206\u522b\u4ee3\u8868\u9ad8\u5ea6\u548c\u5bbd\u5ea6\u3002  \u5c06\u4ee5\u4e0a\u5185\u5bb9\u4fdd\u5b58\u4e3a .scpt \u6587\u4ef6\u540e\uff0c\u5728\u7ec8\u7aef\u5185\u4f7f\u7528 osascript \u547d\u4ee4\u5373\u53ef\u8fd0\u884c\uff1a\nosascript resize.scpt ","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-resize-window-programmatically\/","summary":"<p>\u535a\u5ba2\u53c8\u8df3\u7968\u4e00\u9635\u5b50\uff0c\u4e0d\u8fc7\u6700\u8fd1\u5e76\u6ca1\u6709\u95f2\u7740\uff0c\u800c\u662f\u628a\u4e1a\u4f59\u65f6\u95f4\u5168\u90e8\u6295\u5165\u5230\u4e86 <a href=\"https:\/\/github.com\/wi1dcard\/laravel-deployment\" target=\"_blank\">Laravel \u90e8\u7f72\u8bfe\u7a0b<\/a>\u3002\u5728\u5199\u4f5c\u65f6\u7ecf\u5e38\u9700\u8981\u5bf9\u7a97\u53e3\u622a\u56fe\uff0c\u4e3a\u4e86\u63d0\u9ad8\u9605\u8bfb\u4f53\u9a8c\uff0c\u9700\u786e\u4fdd\u622a\u56fe\u5927\u5c0f\u7edf\u4e00\uff1b\u56e0\u6b64\u5982\u4f55\u8ba9\u7a97\u53e3 <strong>\u5feb\u901f<\/strong> \u5730\u7f29\u653e\u4e3a\u6307\u5b9a\u50cf\u7d20\u7684 <strong>\u7cbe\u786e<\/strong> \u5927\u5c0f\uff0c\u6210\u4e86\u4e00\u4e2a\u4e0d\u53ef\u6216\u7f3a\u7684\u9700\u6c42\u3002<\/p>","title":"\u4f7f\u7528 AppleScript \u7cbe\u786e\u5730\u8bbe\u7f6e macOS \u7a97\u53e3\u5927\u5c0f"},{"content":"\u672c\u6587\u4e3a\u300a\u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528\u300b\u7684\u9884\u4e60\u8865\u5145\u7bc7\u3002\n\u7b80\u4ecb \u6240\u8c13\u300c\u57fa\u7840\u8bbe\u65bd\uff08Infrastructure\uff09\u300d\uff0c\u662f\u4e91\u65f6\u4ee3\u5174\u8d77\u540e\u6d41\u884c\u8d77\u6765\u7684\u4e00\u4e2a\u540d\u8bcd\u3002\u670d\u52a1\u5668\u3001\u4ea4\u6362\u673a\u3001\u8d1f\u8f7d\u5747\u8861\u7b49\u7b49\uff0c\u90fd\u53ef\u4ee5\u79f0\u4f5c\u662f\u57fa\u7840\u8bbe\u65bd\u3002\n\u57fa\u7840\u8bbe\u65bd\u901a\u5e38\u662f\u8f6f\u4ef6\u9879\u76ee\u7684\u786c\u4ef6\u8f7d\u4f53\u3002\u90e8\u7f72\u7684\u8fc7\u7a0b\uff0c\u53ef\u7406\u89e3\u4e3a\u5c06\u8f6f\u4ef6\u5b89\u88c5\u5230\u57fa\u7840\u8bbe\u65bd\u7684\u8fc7\u7a0b\u3002\u5728\u5b9e\u9645\u9879\u76ee\u90e8\u7f72\u524d\uff0c\u901a\u5e38\u9996\u5148\u8981\u786e\u5b9a\u4f60\u7684\u9879\u76ee\u300c\u9700\u8981\u54ea\u4e9b \u57fa\u7840\u8bbe\u65bd\u300d\u3002\n\u4e91\u670d\u52a1\u5668  \u4e91\u670d\u52a1\u5668\uff08Elastic Compute Services\uff09\u662f\u4e00\u79cd\u7b80\u5355\u9ad8\u6548\u3001\u5b89\u5168\u53ef\u9760\u3001\u5904\u7406\u80fd\u529b\u53ef\u5f39\u6027\u4f38\u7f29\u7684\u8ba1\u7b97\u670d\u52a1\u3002\n \u66f4\u76f4\u767d\u5730\u8bf4\uff0c\u4f60\u53ef\u4ee5\u5c06\u4e00\u53f0\u4e91\u670d\u52a1\u5668\u7406\u89e3\u4e3a\u4e00\u53f0\u72ec\u7acb\u7684\u300c\u7535\u8111\u300d\uff0c\u53ea\u4e0d\u8fc7\u8fd9\u53f0\u300c\u7535\u8111\u300d\u7684\u786c\u4ef6\u54b1\u4eec\u770b\u4e0d\u89c1\u6478\u4e0d\u7740\uff0c\u5b83\u6258\u7ba1\u4e8e\u4e91\u670d\u52a1\u5382\u5546\u3002\u5728\u4e91\u670d\u52a1\u5382\u5546\u63d0\u4f9b\u7684\u7ba1\u7406\u9875\u9762\uff0c\u4f60\u53ef\u4ee5\u7ed9\u4e91\u670d\u52a1\u5668\u5347\u7ea7\u3001\u964d\u7ea7\u914d\u7f6e\uff0c\u4ee5\u53ca\u8fdb\u884c\u5f00\u5173\u673a\u3001\u91cd\u88c5\u7cfb\u7edf\u7b49\u5e38\u89c1\u7684\u7ba1\u7406\u64cd\u4f5c\u3002\n\u5b9e\u9645\u4e0a\uff0c\u4e91\u670d\u52a1\u5382\u5546\u53ea\u662f\u5c06\u786c\u4ef6\u5212\u5206\u7ed9\u4e91\u670d\u52a1\u5668\uff0c\u5e76\u51fa\u79df\u7ed9\u6211\u4eec\uff0c\u800c\u6211\u4eec\u5219 \u5177\u5907\u5bf9\u8be5\u670d\u52a1\u5668\u8f6f\u4ef6\u4e0e\u6570\u636e\u65b9\u9762\u7684\u5b8c\u5168\u3001\u7edd\u5bf9\u63a7\u5236\u6743\u3002\n\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u4e91\u670d\u52a1\u5668\u662f\u4e00\u5207\u670d\u52a1\u7684\u57fa\u7840\uff1b\u540e\u7eed\u7684\u8bfe\u7a0b\u5c06\u4f1a\u628a Laravel \u9879\u76ee\u90e8\u7f72\u5230\u4e91\u670d\u52a1\u5668\u4e2d\u3002\n\u4e3a\u4ec0\u4e48\u4e0d\u5e94\u8be5\u4f7f\u7528\u865a\u62df\u4e3b\u673a \u9996\u5148\uff0c\u6211\u4eec\u9700\u8981\u660e\u767d\u4ec0\u4e48\u662f \u865a\u62df\u4e3b\u673a\u3002\n \u865a\u62df\u4e3b\u673a\uff08Virtual Hosts\uff09\u662f\u6307\u5728\u670d\u52a1\u5668\u4e0a\u5206\u914d\u4e00\u5b9a\u7684\u78c1\u76d8\u7a7a\u95f4\uff0c\u7528\u6237\u53ef\u4ee5\u79df\u7528\u6b64\u90e8\u5206\u7a7a\u95f4\uff0c\u4ee5\u4f9b\u7528\u6237\u653e\u7f6e\u7ad9\u70b9\uff0c\u5e76\u63d0\u4f9b\u7b80\u6613\u7684\u5b58\u50a8\u548c\u4f20\u8f93\u529f\u80fd\u3002\n \u53ef\u4ee5\u770b\u51fa\uff0c\u865a\u62df\u4e3b\u673a\u662f\u5728\u670d\u52a1\u5668\u7684\u57fa\u7840\u4e0a\u8fdb\u884c\u4e8c\u6b21\u5212\u5206\uff0c\u5c06\u539f\u672c\u5c5e\u4e8e\u5355\u53f0\u670d\u52a1\u5668\u7684\u8d44\u6e90\u5206\u914d\u6210\u4e00\u4e2a\u4e2a\u5c0f\u5757\u3002\u5982\u679c\u5c06\u4e91\u670d\u52a1\u5382\u5546\u6bd4\u4f5c\u62e5\u6709\u786c\u4ef6\u7684\u623f\u4e1c\uff0c\u90a3\u4e48\u6211\u4eec\u79df\u7528\u4e91\u670d\u52a1\u5668\u5219\u53ef\u4ee5\u770b\u4f5c\u662f\u79df\u623f\u3002\u800c\u865a\u62df\u4e3b\u673a\uff0c\u5219\u662f\u79df\u623f\u540e\u6446\u4e0a\u591a\u4e2a\u5e8a\u4f4d\u518d\u6b21\u51fa\u79df\uff0c\u6210\u4e3a\u96c6\u4f53\u5bbf\u820d\u3002\n\u5982\u540c\u4e0a\u6587\u6240\u8bf4\uff0c\u6211\u4eec\u53ef\u4ee5\u5b8c\u5168\u63a7\u5236\u4e00\u53f0\u4e91\u670d\u52a1\u5668\u7684\u8f6f\u4ef6\u90e8\u5206\uff0c\u4f46\u865a\u62df\u4e3b\u673a\u5f80\u5f80\u53ef\u63a7\u8303\u56f4\u5341\u5206\u6709\u9650\uff0c\u5f88\u5c11\u6709\u865a\u62df\u4e3b\u673a\u63d0\u4f9b\u5546\u652f\u6301\u5b89\u88c5 PHP \u6269\u5c55\u3001\u914d\u7f6e FPM \u53c2\u6570\uff0c\u66f4\u522b\u63d0\u6267\u884c Composer \u547d\u4ee4\u3001\u6307\u5b9a\u7cfb\u7edf\u7248\u672c\uff0c\u8fd9 \u5bf9\u9879\u76ee\u7684\u90e8\u7f72\u8fc7\u7a0b\u662f\u975e\u5e38\u4e0d\u5229\u7684\u3002\n\u53e6\u5916\uff0c\u865a\u62df\u4e3b\u673a\u6570\u636e\u9694\u79bb\u6027\u5dee\uff0c\u5f88\u96be\u4fdd\u8bc1\u5176\u53ef\u9760\u6027\u548c\u5b89\u5168\u6027\uff1b\u4e00\u53f0\u670d\u52a1\u5668\u53ef\u80fd\u540c\u65f6\u300c\u8d85\u8f7d\u300d\u4e86\u6210\u767e\u4e0a\u5343\u4e2a\u865a\u62df\u4e3b\u673a\uff0c\u4e0d\u4ec5 \u901f\u5ea6\u6162\uff0c\u4e14\u5bb9\u6613 \u53d7\u5230\u5176\u5b83\u865a\u62df\u4e3b\u673a\u7684\u5f71\u54cd\u3002\u76f8\u6bd4\u4e4b\u4e0b\uff0c\u591a\u6570\u4e91\u670d\u52a1\u5382\u5546\u76ee\u524d\u6280\u672f\u5df2\u7ecf\u6bd4\u8f83\u6210\u719f\u7a33\u5b9a\uff0c\u56e0\u6b64\u8bf7\u4f7f\u7528\u4e91\u670d\u52a1\u5668\uff0c\u907f\u514d\u4f7f\u7528\u865a\u62df\u4e3b\u673a\u3002\n\u53ef\u9009\u7684\u72ec\u7acb\u670d\u52a1 \u4e3b\u6d41\u4e91\u670d\u52a1\u5382\u5546\u9664\u4e86\u63d0\u4f9b\u57fa\u672c\u7684\u4e91\u670d\u52a1\u5668\u4e4b\u5916\uff0c\u5927\u591a\u8fd8\u6709\u72ec\u7acb\u7684 \u6570\u636e\u5e93\u670d\u52a1\uff08\u4f8b\u5982 MySQL\uff09\u3001\u7f13\u5b58\u670d\u52a1\uff08\u4f8b\u5982 Redis\uff09\u7b49\u3002\u8fd9\u4e9b\u670d\u52a1\u4e5f\u662f\u901a\u8fc7\u4e91\u670d\u52a1\u5668\u4f5c\u4e3a\u8f7d\u4f53\uff0c\u5c06\u5b83\u4eec\u90e8\u7f72\u5728\u4e91\u670d\u52a1\u5668\u4e0a\u51fa\u79df\u7ed9\u6211\u4eec\u3002\n\u4f60\u53ef\u80fd\u60f3\u95ee\uff0c\u90a3\u6211\u4e3a\u4ec0\u4e48\u4e0d\u81ea\u5df1\u90e8\u7f72\u5462\uff0c\u4f55\u5fc5\u4e70\u72ec\u7acb\u7684\u670d\u52a1\uff1f\u5176\u5b9e\uff0c\u5e55\u540e\u7684\u5de5\u7a0b\u5e08\u4eec\u901a\u5e38\u4e3a\u8fd9\u4e9b\u670d\u52a1\u8fdb\u884c\u4e86\u5927\u91cf\u4f18\u5316\uff0c\u662f\u603b\u7ed3\u4e86\u8bb8\u591a\u5b9e\u6218\u7ecf\u9a8c\u540e\u7ed9\u51fa\u7684\u66f4\u4e13\u4e1a\u3001\u66f4\u5feb\u6377\u7684\u89e3\u51b3\u65b9\u6848\uff1b\u5e76\u4e14\u670d\u52a1\u5185\u90e8\u7684\u8fd0\u7ef4\u5de5\u4f5c\u4ea4\u7ed9\u4e86\u4e91\u670d\u52a1\u5382\u5546\uff0c\u6211\u4eec\u53ef\u4ee5\u66f4\u52a0\u4e13\u6ce8\u4e8e\u5982\u4f55\u5b9e\u73b0\u5177\u4f53\u7684\u4e1a\u52a1\u3002\n\u56e0\u6b64\uff0c\u5728\u6ca1\u6709\u7279\u6b8a\u8981\u6c42\u7684\u60c5\u51b5\u4e0b\uff0c\u5982\u679c\u53ef\u4ee5\uff0c\u6211\u66f4\u63a8\u8350\u4f7f\u7528\u8fd9\u4e9b\u72ec\u7acb\u7684\u670d\u52a1\uff0c\u7701\u5fc3\u7701\u529b\u53c8\u7701\u65f6\u3002\n\u4e3b\u6d41\u4e91\u670d\u52a1\u5382\u5546 \u6765\u81ea\u56fd\u5185\uff1a\n \u963f\u91cc\u4e91\uff1a\u963f\u91cc\u5df4\u5df4\u51fa\u54c1\uff0c\u56fd\u5185\u5e02\u573a\u5360\u6709\u7387\u8fde\u7eed\u591a\u5e74\u4fdd\u6301\u7b2c\u4e00\u3002 \u817e\u8baf\u4e91\uff1a\u817e\u8baf\u51fa\u54c1\uff0c\u51ed\u501f\u591a\u5e74\u7684 IM \u6280\u672f\u79ef\u7d2f\uff0c\u63d0\u4f9b\u4e00\u4e9b\u4e0d\u9519\u7684\u7279\u8272\u670d\u52a1\u3002 \u534e\u4e3a\u4e91\uff1a\u534e\u4e3a\u51fa\u54c1\uff0c\u7531\u4e8e\u5176\u5177\u5907\u786c\u4ef6\u7814\u53d1\u751f\u4ea7\u80fd\u529b\uff0c\u5728\u90e8\u5206\u9886\u57df\u6709\u540e\u6765\u5c45\u4e0a\u4e4b\u52bf\u3002  \u6765\u81ea\u56fd\u5916\uff1a\n Amazon Web Services\uff08AWS\uff09\uff1a\u4e9a\u9a6c\u900a\u51fa\u54c1\uff0c\u8001\u724c\u4e91\u670d\u52a1\u5546\u4e4b\u4e00\u3002\u6709 \u4e2d\u56fd\u7279\u4f9b\u7248\uff0c\u4f46\u529f\u80fd\u5927\u5927\u7f29\u6c34\u3002 Azure\uff1a\u5fae\u8f6f\u51fa\u54c1\uff0c\u4ef7\u683c\u76f8\u5bf9\u8f83\u9ad8\uff0c\u5e26\u5bbd\u76f8\u5bf9\u8f83\u597d\u3002\u6709 \u4e2d\u56fd\u7279\u4f9b\u7248\uff0c\u529f\u80fd\u540c\u6837\u5927\u5927\u7f29\u6c34\u3002 Google Cloud Platform\uff08GCP\uff09\uff1a\u8c37\u6b4c\u51fa\u54c1\uff0c\u754c\u9762\u76f8\u5bf9\u7f8e\u89c2\uff0c\u5bf9\u65b0\u6280\u672f\u7684\u652f\u6301\u8f83\u597d\u3002\u4f46\u88ab\u5899\uff0c\u4e14\u65e0\u4e2d\u56fd\u533a\u3002  \u5305\u5e74\u5305\u6708\u8fd8\u662f\u6309\u65f6\u957f\u4ed8\u8d39\uff1f \u5927\u591a\u4e91\u670d\u52a1\u63d0\u4f9b\u4e24\u79cd\u79df\u8d41\u8ba1\u8d39\u6a21\u5f0f\uff1a\u5305\u5e74\u6216\u5305\u6708\u9884\u4ed8\u8d39 \u4ee5\u53ca \u6309\u65f6\u957f\u540e\u4ed8\u8d39\u3002\n\u5305\u5e74\u3001\u5305\u6708\u7684\u8ba1\u8d39\u65b9\u5f0f\u6bd4\u8f83\u7b80\u5355\uff0c\u5728\u8d2d\u4e70\u65f6\u652f\u4ed8\u5b9a\u91cf\u8d39\u7528\u5373\u53ef\uff1b\u5728\u670d\u52a1\u672a\u8fc7\u671f\u524d\u4f60\u53ef\u4ee5\u4efb\u610f\u4f7f\u7528\uff0c\u5230\u671f\u540e\u5c06\u4f1a\u81ea\u52a8\u9500\u6bc1\u3002\n\u6309\u65f6\u957f\u7684\u8ba1\u8d39\u5355\u4f4d\u901a\u5e38\u66f4\u52a0\u7cbe\u786e\uff0c\u4f8b\u5982 \u6bcf\u5c0f\u65f6 \u751a\u81f3 \u6bcf\u5206\u949f\u3001\u6bcf\u79d2\uff1b\u4f60\u53ef\u4ee5\u968f\u65f6\u521b\u5efa\u670d\u52a1\uff0c\u4e5f\u53ef\u4ee5\u968f\u65f6\u9500\u6bc1\u3002\u5728\u670d\u52a1\u88ab\u9500\u6bc1\u4e4b\u524d\uff0c\u670d\u52a1\u5546\u5c06\u6301\u7eed\u4ece\u4f60\u7684\u8d26\u6237\u5185\u6263\u8d39\u3002\n\u6309\u65f6\u957f\u901a\u5e38\u6bd4\u5305\u6708\u7565\u8d35\u4e9b\uff0c\u4f46\u66f4\u52a0\u300c\u968f\u5fc3\u6240\u6b32\u300d\uff1b\u800c\u5305\u6708\u4e0d\u5fc5\u62c5\u5fc3\u5fd8\u8bb0\u9500\u6bc1\u5bfc\u81f4\u8d85\u989d\u8d26\u5355\uff0c\u4f46\u4e5f\u4e0d\u53ef\u907f\u514d\u5730\u4e27\u5931\u4e86\u7075\u6d3b\u6027\u3002\n\u540e\u7eed\u8bfe\u7a0b\u63a8\u8350\u4f7f\u7528\u6309\u65f6\u957f\u4ed8\u8d39\u7684\u4e91\u670d\u52a1\u3002\u5728\u8fd8\u4e0d\u719f\u6089\u76f8\u5173\u914d\u7f6e\u7684\u60c5\u51b5\u4e0b\uff0c\u4f60\u53ef\u4ee5\u4efb\u610f\u521b\u5efa\u3001\u4fee\u6539\u3001\u9500\u6bc1\u5b83\u4eec\uff0c\u800c\u4e0d\u4f1a\u88ab\u56fa\u5b9a\u7684\u4ed8\u8d39\u6a21\u5f0f\u7981\u9522\u3002\n\u6309\u56fa\u5b9a\u5bbd\u5e26\u8fd8\u662f\u6309\u6d41\u91cf\u4ed8\u8d39\uff1f \u4e0e\u4e0a\u6587\u7c7b\u4f3c\uff0c\u56fd\u5185\u4e91\u670d\u52a1\u5668\u7f51\u7edc\u8ba1\u8d39\u65b9\u5f0f\u901a\u5e38\u4e5f\u5206\u4e3a\u4e24\u79cd\uff1a\u6309\u56fa\u5b9a\u5e26\u5bbd\u8ba1\u8d39 \u4ee5\u53ca \u6309\u6d41\u91cf\u8ba1\u8d39\u3002\n\u6309\u5e26\u5bbd\u8ba1\u8d39\u5c06\u670d\u52a1\u5668\u7684\u6700\u9ad8\u5e26\u5bbd\u9650\u5236\u5728\u67d0\u4e2a\u56fa\u5b9a\u503c\uff1b\u65e0\u8bba\u5229\u7528\u7387\u9ad8\u4f4e\uff0c\u662f\u5426\u6709\u6570\u636e\u4f20\u8f93\uff0c\u5e26\u5bbd\u8d8a\u9ad8\uff0c\u4ef7\u683c\u8d8a\u8d35\u3002\n\u6309\u6d41\u91cf\u8ba1\u8d39\u7c7b\u4f3c\u624b\u673a\u6d41\u91cf\uff0c\u53ea\u4e0d\u8fc7\u6211\u4eec\u4e0d\u9700\u8981\u9884\u5145\u503c\uff1b\u670d\u52a1\u5546\u5c06\u5b9e\u65f6\u7edf\u8ba1\u4e91\u670d\u52a1\u5668\u6570\u636e\u4f20\u8f93\u91cf\uff0c\u6309\u7167 \u6bcf GB \u4e00\u5b9a\u4ef7\u683c\u6301\u7eed\u4ece\u4f60\u7684\u8d26\u6237\u5185\u6263\u8d39\u3002\n\u4ee5\u5b9e\u9645\u7ecf\u9a8c\u6765\u770b\uff0c\u6309\u5e26\u5bbd\u8ba1\u8d39\u901a\u5e38\u6bd4\u6309\u6d41\u91cf\u8ba1\u8d39\u6027\u4ef7\u6bd4\u4f4e\uff0c\u56e0\u4e3a\u7edd\u5927\u591a\u6570\u7ad9\u70b9\u5e76\u4e0d\u662f\u6bcf\u65f6\u6bcf\u523b\u90fd\u4fdd\u6301\u7a33\u5b9a\u7684\u8bbf\u95ee\u91cf\uff0c\u5728\u4e1a\u52a1\u4f4e\u8c37\u65f6\u5c3d\u7ba1\u5e26\u5bbd\u5229\u7528\u7387\u5f88\u4f4e\uff0c\u4ecd\u9700\u652f\u4ed8\u540c\u6837\u7684\u8d39\u7528\u3002\u4e0d\u8fc7\u8981\u63d0\u9192\u5927\u5bb6\uff0c\u6309\u6d41\u91cf\u4ed8\u8d39\u7684\u7ad9\u70b9\u9700\u8981\u6ce8\u610f\u907f\u514d\u88ab\u5fc3\u6000\u53f5\u6d4b\u7684\u300c\u5c0f\u4eba\u300d\u6076\u610f\u5237\u6d41\u91cf\uff0c\u5bfc\u81f4\u8d26\u5355\u8d85\u989d\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/cloud-infrastructures\/","summary":"<p>\u672c\u6587\u4e3a\u300a<a href=\"https:\/\/github.com\/wi1dcard\/laravel-deployment\" target=\"_blank\">\u8f7b\u677e\u90e8\u7f72 Laravel \u5e94\u7528<\/a>\u300b\u7684\u9884\u4e60\u8865\u5145\u7bc7\u3002<\/p>","title":"\u4f60\u9700\u8981\u54ea\u4e9b\u4e91\u670d\u52a1\u57fa\u7840\u8bbe\u65bd\uff1f"},{"content":"\u7531\u4e8e macOS \u9ed8\u8ba4\u5206\u533a\u548c\u5377\u90fd\u662f\u5927\u5c0f\u5199\u4e0d\u654f\u611f\u7684\uff0c\u5bf9\u4e8e\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u901a\u5e38\u9700\u8981\u9762\u5bf9\u7684\u662f\u5927\u5c0f\u5199\u654f\u611f\u7684\u73af\u5883\u3002\u5e76\u4e14\uff0c\u8fd9\u4e2a\u5c0f\u5dee\u5f02\u7684\u786e\u5e26\u6765\u4e86\u4e00\u4e9b\u4e0d\u4fbf\uff0c\u4f8b\u5982 \u4f7f\u7528 Git \u65f6\u9047\u5230\u7684\u5751\u3002\u7136\u800c\uff0c\u81ea\u5df1\u53c8\u6ca1\u6709\u52c7\u6c14\u91cd\u65b0\u683c\u5f0f\u5316\u3001\u88c5\u7cfb\u7edf\u3002\u76f4\u5230\u6700\u8fd1\uff0c\u5728\u8ddf\u540c\u4e8b\u804a\u5929\u65f6\u7ed9\u4e86\u6211\u4e00\u4e2a\u542f\u53d1\u2026\u2026\n\u601d\u8def macOS \u6700\u65b0\u7684 APFS \u6587\u4ef6\u7cfb\u7edf\u652f\u6301\u5728 Container \u5185\u4efb\u610f\u521b\u5efa Volume\uff08\u5377\uff09\uff0c\u6bd4\u5206\u533a\u7b80\u5355\u5feb\u6377\u5f88\u591a\uff0c\u540c\u65f6\u8fd8\u53ef\u4ee5\u5355\u72ec\u6307\u5b9a\u662f\u5426\u5927\u5c0f\u5199\u654f\u611f\u3002\u518d\u52a0\u4e0a Unix \u80fd\u591f\u4efb\u610f\u6302\u8f7d\u7684\u7279\u6027\uff0c\u56e0\u6b64\u6211\u53ea\u9700\u521b\u5efa\u4e00\u4e2a\u65b0\u5377\uff0c\u5c06\u9879\u76ee\u6587\u4ef6\u79fb\u52a8\u8fc7\u53bb\uff0c\u968f\u540e\u5c06\u8be5\u5377\u6302\u8f7d\u81f3\u539f\u4ee3\u7801\u76ee\u5f55\u5373\u53ef\u3002\n\u5177\u4f53\u64cd\u4f5c\u65b9\u5f0f\u5982\u4e0b\u3002\n\u6b65\u9aa4 \u521b\u5efa\u5927\u5c0f\u5199\u654f\u611f\u7684\u5377 \u9996\u5148\uff0c\u6253\u5f00 Disk Utility\uff0c\u786e\u4fdd\u4f60\u7684\u6587\u4ef6\u7cfb\u7edf\u662f APFS\uff1b\u82e5\u662f HFS\uff0c\u8bf7 \u5347\u7ea7\u3002\n\u5728\u5de6\u4fa7\u5217\u8868\u53f3\u952e\u5355\u51fb Macintosh HD\uff0c\u9009\u62e9 Add APFS Volume\u3002\n\u7ed9\u5b83\u8d77\u4e2a\u540d\u5b57\uff0c\u968f\u540e Format \u9009\u62e9 APFS (Case-sensitive)\uff0c\u52a1\u5fc5\u6ce8\u610f\u5927\u5c0f\u5199\u654f\u611f\u3002\n\u786e\u8ba4\u65e0\u8bef\u540e\u70b9\u51fb Add \u5373\u53ef\u3002\n\u8fc1\u79fb\u6570\u636e \u6ca1\u6709\u95ee\u9898\u7684\u8bdd\uff0c\u65b0\u521b\u5efa\u7684\u5377\u5e94\u8be5\u5df2\u7ecf\u6302\u8f7d\u5230 \/Volumes\/&lt;NAME&gt; \u76ee\u5f55\uff0c\u63a5\u4e0b\u6765\u9700\u8981\u628a\u539f\u6709\u4ee3\u7801\u6587\u4ef6\u79fb\u52a8\u5230\u8fd9\u4e2a\u5377\u3002\u4f7f\u7528 mv \u547d\u4ee4\uff0c\u6216\u662f\u901a\u8fc7 Finder \u64cd\u4f5c\u5747\u53ef\u3002\n\u4fee\u6539\u6302\u8f7d\u70b9 \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u7cfb\u7edf\u4f1a\u5c06\u6240\u6709\u5377\u6302\u8f7d\u81f3 \/Volumes \u76ee\u5f55\u4e0b\uff0c\u4ee5\u5377\u540d\u533a\u5206\u3002\u6211\u7684\u9879\u76ee\u5b58\u653e\u4e8e \/Projects\uff0c\u56e0\u6b64\u9700\u8981\u5c06\u65b0\u5377\u6302\u8f7d\u5230\u8be5\u76ee\u5f55\u3002\n\u518d\u6b21\u6253\u5f00 Disk Utility\uff0c\u5728\u5de6\u4fa7\u5217\u8868\u53f3\u952e\u5355\u51fb\u65b0\u521b\u5efa\u7684\u5377\uff0c\u9009\u62e9 Get Info\u3002\u70b9\u51fb File system UUID \u4e00\u884c\uff0c\u4f7f\u7528 Command + C \u590d\u5236\u51fa\u6765\uff1a\nFile system UUID : XXXXXXXX-ABCD-DCBA-1234-XXXXXXXXXXXX \u8bb0\u4f4f\u5192\u53f7\u540e\u7684 UUID\u3002\u63a5\u4e0b\u6765\u70b9\u51fb Unmount \u6309\u94ae\u5378\u8f7d\u8be5\u5377\u3002\n\u6253\u5f00\u7ec8\u7aef\uff0c\u4f7f\u7528 sudo vifs \u5373\u53ef\u7f16\u8f91 \/etc\/fstab \u6587\u4ef6\uff0c\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\u5e76\u4fdd\u5b58\uff1a\nUUID=XXXXXXXX-ABCD-DCBA-1234-XXXXXXXXXXXX &lt;MOUNT_POINT&gt; apfs rw 0 2 \u8bf7\u6ce8\u610f\u5c06 &lt;MOUNT_POINT&gt; \u66ff\u6362\u4e3a\u6302\u8f7d\u76ee\u5f55\uff0c\u4f8b\u5982 \/Projects\u3002\u82e5\u8be5\u76ee\u5f55\u4e0d\u5b58\u5728\uff0c\u4e0d\u8981\u5fd8\u8bb0\u521b\u5efa\u5b83\u3002\n\u91cd\u65b0\u6302\u8f7d \u91cd\u65b0\u70b9\u51fb Mount \u6309\u94ae\u6216\u662f mount -a \u547d\u4ee4\u5747\u53ef\u3002\n\u5b8c\u6210\uff01\u6548\u679c\u5982\u4e0b\uff1a\n\u7ed3\u8bed \u53c2\u8003\uff1a\n https:\/\/apple.stackexchange.com\/questions\/291149\/permanently-change-mount-point-of-volume ","permalink":"https:\/\/wi1dcard.dev\/posts\/use-case-sensitive-apfs-volume\/","summary":"<p>\u7531\u4e8e macOS \u9ed8\u8ba4\u5206\u533a\u548c\u5377\u90fd\u662f\u5927\u5c0f\u5199\u4e0d\u654f\u611f\u7684\uff0c\u5bf9\u4e8e\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u901a\u5e38\u9700\u8981\u9762\u5bf9\u7684\u662f\u5927\u5c0f\u5199\u654f\u611f\u7684\u73af\u5883\u3002\u5e76\u4e14\uff0c\u8fd9\u4e2a\u5c0f\u5dee\u5f02\u7684\u786e\u5e26\u6765\u4e86\u4e00\u4e9b\u4e0d\u4fbf\uff0c\u4f8b\u5982 <a href=\"https:\/\/learnku.com\/articles\/3782\/a-pit-reminder-a-class-or-a-trait-suddenly-can-not-find\" target=\"_blank\">\u4f7f\u7528 Git \u65f6\u9047\u5230\u7684\u5751<\/a>\u3002\u7136\u800c\uff0c\u81ea\u5df1\u53c8\u6ca1\u6709\u52c7\u6c14\u91cd\u65b0\u683c\u5f0f\u5316\u3001\u88c5\u7cfb\u7edf\u3002\u76f4\u5230\u6700\u8fd1\uff0c\u5728\u8ddf\u540c\u4e8b\u804a\u5929\u65f6\u7ed9\u4e86\u6211\u4e00\u4e2a\u542f\u53d1\u2026\u2026<\/p>","title":"\u4f7f\u7528\u5927\u5c0f\u5199\u654f\u611f\u7684 APFS \u5377\u5b58\u50a8\u4ee3\u7801"},{"content":"\u524d\u4e9b\u5929\u7ed9\u547d\u4ee4\u884c\u8bbe\u7f6e\u6807\u9898\u9047\u5230\u4e00\u5947\u8469\u95ee\u9898\uff0c\u6700\u7ec8\u8c03\u8bd5\u53d1\u73b0\u662f Oh-My-Zsh \u7684\u9505\u3002\n\u5728\u542f\u7528 Oh-My-Zsh \u540e\uff0c\u4f7f\u7528\u547d\u4ee4\uff1a\necho -e &#34;\\033];this is the title\\007&#34; \u5c45\u7136\u65e0\u6cd5\u4fee\u6539\u7ec8\u7aef\u7a97\u53e3\u6807\u9898\uff1f\u4e0d\u8fc7\uff0c\u4ed4\u7ec6\u89c2\u5bdf\u8fd8\u662f\u4f1a\u6ce8\u610f\u5230\u6807\u9898\u300c\u95ea\u300d\u4e86\u4e00\u4e0b\uff0c\u8bf4\u660e\u8fd8\u662f\u5b58\u5728\u6548\u679c\uff0c\u53ea\u4e0d\u8fc7\u88ab\u67d0\u79cd\u300c\u795e\u79d8\u529b\u91cf\u300d\u91cd\u8bbe\u4e86\u56de\u6765\uff0c\n\u6700\u5f00\u59cb\u6000\u7591\u662f\u4e0d\u662f iTerm2 \u4e4b\u7c7b\u7684\u9505\uff0c\u6362\u6210 Terminal \u95ee\u9898\u4f9d\u65e7\u3002\n\u968f\u540e\u5f00\u59cb\u5c1d\u8bd5\u4f7f\u7528 bash \u6267\u884c\u4e0a\u6587\u7684\u547d\u4ee4\uff0c\u6b63\u5e38\u5de5\u4f5c\u3002\u56e0\u6b64\u95ee\u9898\u5e94\u8be5\u51fa\u5728 Zsh \u5468\u8fb9\u3002\n\u4e8e\u662f\u4f7f\u7528 zsh -d -f\uff08\u5373\u4e0d\u52a0\u8f7d\u4efb\u4f55 RC \u6587\u4ef6\uff0c\u6700\u539f\u59cb\u7684 zsh\uff09\u518d\u6b21\u8c03\u8bd5\uff0c\u53ef\u4ee5\u6b63\u5e38\u5de5\u4f5c\u3002\u6240\u4ee5\u7f6a\u9b41\u7978\u9996\u5e94\u5f53\u5c31\u9690\u85cf\u5728 ~\/.zshrc \u4e4b\u4e2d\u3002\n\u6700\u7ec8\u7ecf\u8fc7\u6392\u67e5\uff0c\u53d1\u73b0\u662f\u7531\u4e8e Oh-My-Zsh \u7684\u4e00\u4e2a\u540d\u4e3a Auto title \u7684\u529f\u80fd\u9020\u6210\u7684\uff0c\u53c2\u8003\uff1ahttps:\/\/github.com\/robbyrussell\/oh-my-zsh\/issues\/5700\u3002\n\u5927\u81f4\u89e3\u51b3\u65b9\u6848\u6709\u4e24\u79cd\uff1a\n \u5728 .zshrc \u5185\u5199\u5165\u73af\u5883\u53d8\u91cf DISABLE_AUTO_TITLE=&quot;true&quot;\u3002 \u56e0\u4e3a\u6211\u7684\u6700\u7ec8\u76ee\u7684\u662f\u4fee\u6539\u800c\u975e\u7981\u7528\uff0c\u6545\u4ea6\u53ef\u76f4\u63a5\u4fee\u6539 ZSH_THEME_TERM_TITLE_IDLE \u73af\u5883\u53d8\u91cf\u4f5c\u4e3a\u7a7a\u95f2\u65f6\u7684\u6807\u9898\uff0c\u53c2\u8003 \u8fd9\u6bb5\u6e90\u7801\u3002  \u6700\u7ec8\uff0c\u6211\u5728 ~\/.zshrc \u672b\u5c3e\u52a0\u5165\u4e00\u884c\uff1a\nZSH_THEME_TERM_TITLE_IDLE=&#34;%~&#34; # \u5c06\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u77ed\u8def\u5f84\u8bbe\u4e3a\u7ec8\u7aef\u6807\u9898 \u6ce8\u610f\uff0c\u4ee5\u4e0a\u8bed\u53e5\u5e94\u5728 Oh-My-Zsh \u8f7d\u5165\u4e4b\u540e\uff0c\u5426\u5219\u5c06\u4f1a\u88ab \u8fd9\u6bb5\u6e90\u7801 \u8986\u76d6\u3002\n\u95ee\u9898\u89e3\u51b3\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/change-terminal-title-in-zsh\/","summary":"<p>\u524d\u4e9b\u5929\u7ed9\u547d\u4ee4\u884c\u8bbe\u7f6e\u6807\u9898\u9047\u5230\u4e00\u5947\u8469\u95ee\u9898\uff0c\u6700\u7ec8\u8c03\u8bd5\u53d1\u73b0\u662f Oh-My-Zsh \u7684\u9505\u3002<\/p>","title":"\u5728 Oh-My-Zsh \u5185\u8bbe\u7f6e\u547d\u4ee4\u884c\u6807\u9898"},{"content":"reorx\/httpstat \u662f\u4e00\u6b3e\u66f4\u52a0\u6e05\u6670\u6613\u8bfb\u7684 cURL \u5de5\u5177\u3002\u5176\u672c\u610f\u662f\u5c06 cURL \u8bf7\u6c42\u7684\u7edf\u8ba1\u6570\u636e\u56fe\u5f62\u5316\u3001\u53ef\u89c6\u5316\uff0c\u4f46\u4e5f\u53ef\u4f5c\u4e3a\u65e5\u5e38\u7684 HTTP \u5ba2\u6237\u7aef\u4f7f\u7528\u3002\n\u6548\u679c\u5982\u4e0b\uff1a\n\u76f8\u6bd4\u4e8e\u7e41\u590d\u7ec6\u81f4\u7684 cURL \u9009\u9879\uff0c\u4f7f\u7528\u6b64\u9879\u76ee\u53ef\u5feb\u901f\u67e5\u770b\u54cd\u5e94\u5934\u53ca\u76f8\u5173\u7684\u7edf\u8ba1\u6570\u636e\u3002\n\u5b89\u88c5\u65b9\u5f0f\u5341\u5206\u7b80\u5355\uff0c\u901a\u8fc7 Python \u7684\u5305\u7ba1\u7406\u5668 pip \u6216\u662f Homebrew \u5747\u53ef\uff1a\npip install httpstat # \u6216 brew install httpstat \u7531\u4e8e\u8be5\u9879\u76ee\u5b9e\u9645\u662f\u4e2a\u5355\u6587\u4ef6 Python \u811a\u672c\uff0c\u6240\u4ee5\u4f5c\u8005\u8fd8\u7ed9\u51fa\u4e86\u76f4\u63a5\u4e0b\u8f7d\u4f7f\u7528\u7684\u65b9\u5f0f\uff0c\u5728\u90e8\u5206\u573a\u666f\u4e0b\u5341\u5206\u6709\u7528\uff1a\nwget https:\/\/raw.githubusercontent.com\/reorx\/httpstat\/master\/httpstat.py \u540c\u65f6\uff0c\u7531\u4e8e\u672c\u9879\u76ee\u662f cURL \u7684\u4e8c\u6b21\u5305\u88c5\uff0c\u5176\u5185\u90e8\u4ecd\u65e7\u901a\u8fc7 curl \u547d\u4ee4\u5b9e\u73b0\uff0c\u6240\u4ee5\u652f\u6301\u5927\u91cf cURL \u53c2\u6570\uff0c\u9762\u5bf9\u590d\u6742\u7684\u8bf7\u6c42\u6570\u636e\u540c\u6837\u5f97\u5fc3\u5e94\u624b\uff0c\u4f8b\u5982\uff1a\nhttpstat httpbin.org\/post -X POST --data-urlencode &#34;a=b&#34; -v \u53e6\u5916\uff0c\u8be5\u9879\u76ee\u8fd8\u6709\u5176\u5b83\u8bed\u8a00\u7248\u672c\uff0c\u4f8b\u5982\uff1a\n Go: davecheney\/httpstat Bash: b4b4r07\/httpstat Node.js: yosuke-furukawa\/httpstat PHP: talhasch\/php-httpstat  \u901a\u8fc7\u67e5\u770b\u6e90\u7801\u8fdb\u884c\u4e00\u756a\u6bd4\u8f83\uff0c\u5176\u4e2d Bash \u548c PHP \u7248\u672c\u5747\u91c7\u7528\u4e0e Python\uff08\u4e5f\u5c31\u662f\u539f\u7248\uff09\u540c\u6837\u7684\u5b9e\u73b0\u65b9\u5f0f\uff0c\u5373\u901a\u8fc7 curl \u547d\u4ee4\u5b9e\u73b0\uff1b\u800c Go \u548c Node.js \u7248\u672c\u5219\u4e0d\u4f9d\u8d56\u4e8e curl \u547d\u4ee4\uff0c\u76f4\u63a5\u4f7f\u7528\u7f51\u7edc\u5e93\u53d1\u8d77\u8bf7\u6c42\u5e76\u8f93\u51fa\u7edf\u8ba1\u6570\u636e\u3002\u8fd9\u4e24\u79cd\u5b9e\u73b0\u65b9\u5f0f\u5404\u6709\u4f18\u52a3\uff0c\u6211\u7684\u503e\u5411\u5982\u4e0b\uff1a\n Python \u7248\u672c\u9002\u5408\u6709 Python \u73af\u5883\uff0c\u4e14\u9700\u8981\u4e0e curl \u547d\u4ee4\u9ad8\u5ea6\u517c\u5bb9\u7684\u573a\u666f\u3002 Bash \u7248\u672c\u9002\u5408\u65e0 Python \u73af\u5883\uff0c\u4e14\u9700\u8981\u4e0e curl \u547d\u4ee4\u9ad8\u5ea6\u517c\u5bb9\u7684\u573a\u666f\u3002 Go \u7248\u672c\u65e0\u987b\u591a\u8a00\uff0c\u9002\u5408\u96f6\u4f9d\u8d56\u573a\u666f\u3002 Node.js \u548c PHP \u7248\u672c\uff0c\u7528\u4e8e\u5174\u8da3\u7231\u597d\u7814\u7a76\u5427\ud83d\ude02\u3002  \u76ee\u524d\uff0c\u6211\u5728\u6211\u7684 macOS \u4e0a\u5b89\u88c5\u4e86 Python \u7248\u672c\uff0c\u8def\u7531\u5668\u7b49\u7f51\u7edc\u8bbe\u5907\u4e0a\u5b89\u88c5\u4e86 Go \u7248\u672c\u3002\n\u6700\u540e\uff0c\u8be5\u9879\u76ee\u8fd8\u63d0\u4f9b\u4e86\u4e00\u4e9b\u73af\u5883\u53d8\u91cf\u7528\u4e8e\u8f93\u51fa\u901f\u5ea6\u7b49\uff0c\u4f8b\u5982\u901a\u8fc7 HTTP \u534f\u8bae\u4e0b\u8f7d CacheFly \u7684\u6587\u4ef6\u6765\u6d4b\u8bd5\u4e0b\u884c\u7f51\u901f\uff1a\nHTTPSTAT_SHOW_SPEED=true httpstat http:\/\/cachefly.cachefly.net\/10mb.test \u6709\u5174\u8da3\u5c31\u770b\u770b\u9879\u76ee\u6587\u6863\u5427\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/easier-curl-with-colors\/","summary":"<p><a href=\"https:\/\/github.com\/reorx\/httpstat\" target=\"_blank\">reorx\/httpstat<\/a> \u662f\u4e00\u6b3e\u66f4\u52a0\u6e05\u6670\u6613\u8bfb\u7684 cURL \u5de5\u5177\u3002\u5176\u672c\u610f\u662f\u5c06 cURL \u8bf7\u6c42\u7684\u7edf\u8ba1\u6570\u636e\u56fe\u5f62\u5316\u3001\u53ef\u89c6\u5316\uff0c\u4f46\u4e5f\u53ef\u4f5c\u4e3a\u65e5\u5e38\u7684 HTTP \u5ba2\u6237\u7aef\u4f7f\u7528\u3002<\/p>","title":"\u66f4\u52a0\u6e05\u6670\u6613\u8bfb\u7684 cURL \u5de5\u5177"},{"content":"\u67e5\u770b Git \u63d0\u4ea4\u5386\u53f2\u7684\u5de5\u5177\u5343\u5343\u4e07\uff0c\u65e0\u8bba\u662f CLI \u8fd8\u662f GUI\u3002\u800c pomber\/git-history \u5219\u662f\u4e00\u6b3e\u80fd\u591f\u4ee5\u52a8\u753b\u5f62\u5f0f\u5feb\u901f\u3001\u76f4\u89c2\u5730\u5c55\u73b0 Git \u4ed3\u5e93\u5185\u6587\u4ef6\u53d8\u52a8\u5386\u53f2\u7684 Web \u5de5\u5177\u3002\n\u60ef\u4f8b\uff0c\u5148\u6765\u770b\u770b\u6548\u679c\u5427\uff1a\n\u4f60\u4e5f\u53ef\u4ee5 \u4eb2\u81ea\u8bd5\u8bd5\u770b\u3002\n\u76f8\u6bd4\u4e8e\u4e3b\u6d41\u7684 Blame \/ Annotation\uff0c\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u66f4\u52a0 \u8fc5\u901f\u76f4\u89c2 \u5730\u67e5\u770b\u5386\u53f2\u63d0\u4ea4\u5bf9\u4e8e\u6587\u4ef6\u7684\u53d8\u52a8\u5f71\u54cd\u3002\n\u8be5\u4f5c\u8005\u9664\u4e86\u5c06\u4ed3\u5e93\u5f00\u6e90\u5916\uff0c\u8fd8\u5c06\u9879\u76ee\u6258\u7ba1\u5728\u4e86 https:\/\/githistory.xyz\/\u3002\u6211\u4eec\u53ef\u4ee5\u6253\u5f00 GitHub \u4e0a\u7684\u4efb\u610f\u6587\u4ef6\uff0c\u7136\u540e\u5c06\u57df\u540d github.com \u66ff\u6362\u4e3a github.githistory.xyz \u5373\u53ef\u4f7f\u7528\u3002\n\u4f3c\u4e4e\u8fd8\u662f\u6709\u4e9b\u9ebb\u70e6\uff0c\u57df\u540d\u6bd4\u8f83\u957f\uff0c\u82e5\u662f\u77ed\u4e00\u4e9b\u5c31\u66f4\u68d2\u4e86\uff1b\u800c\u4e14\u76f4\u63a5\u5728\u5730\u5740\u680f\u4fee\u6539\u57df\u540d\u901a\u5e38\u6ca1\u6709\u8865\u5168\uff0c\u6bd4\u8f83\u75db\u82e6\u3002\n\u8be5\u9879\u76ee\u7ed9\u51fa\u53e6\u4e00\u4e2a\u65b9\u6848\uff1aChrome Extension \u5728\u6b64\uff0c\u6548\u679c\u5982\u4e0b\uff1a\n\u4ee5\u4e0a\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/animate-git-history-on-web\/","summary":"<p>\u67e5\u770b Git \u63d0\u4ea4\u5386\u53f2\u7684\u5de5\u5177\u5343\u5343\u4e07\uff0c\u65e0\u8bba\u662f CLI \u8fd8\u662f GUI\u3002\u800c <a href=\"https:\/\/github.com\/pomber\/git-history\" target=\"_blank\">pomber\/git-history<\/a> \u5219\u662f\u4e00\u6b3e\u80fd\u591f\u4ee5\u52a8\u753b\u5f62\u5f0f\u5feb\u901f\u3001\u76f4\u89c2\u5730\u5c55\u73b0 Git \u4ed3\u5e93\u5185\u6587\u4ef6\u53d8\u52a8\u5386\u53f2\u7684 Web \u5de5\u5177\u3002<\/p>","title":"\u4ee5\u52a8\u753b\u65b9\u5f0f\u76f4\u89c2\u5730\u6d4f\u89c8 Git \u6587\u4ef6\u5386\u53f2"},{"content":"snibox\/snibox \u662f\u4e00\u6b3e\u4f7f\u7528 Ruby on Rails + Vuex \u7f16\u5199\u7684\u4ee3\u7801\u7247\u6bb5\u6258\u7ba1\u670d\u52a1\u3002\u5bf9\u4e8e\u4e00\u7ebf\u7a0b\u5e8f\u5458\u6765\u8bf4\uff0c\u7ecf\u5e38\u4f1a\u63a5\u89e6\u5230\u5927\u91cf\u7684\u4ee3\u7801\u7247\u6bb5\uff08Snippet\uff09\uff0c\u4e0a\u4f20\u5230 Gist \u65e0\u6cd5\u5b8c\u5168 Private\uff0c\u800c Snibox \u5219\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\u3002\n\u6548\u679c \u53e6\u5916\uff0c\u8be5\u9879\u76ee\u8fd8\u6709\u4e2a \u5728\u7ebf Demo\uff0c\u7531\u4e8e\u6258\u7ba1\u4e8e\u514d\u8d39\u7684 Heroku \u670d\u52a1\uff0c\u6240\u4ee5\u9996\u6b21\u8bbf\u95ee\u53ef\u80fd\u9700\u8981\u5927\u6982 30 \u79d2\u65f6\u95f4\u542f\u52a8\u3002\n\u90e8\u7f72 Snibox \u5b98\u65b9\u63d0\u4f9b\u4e86\u4e00\u5957 Docker \u90e8\u7f72\u65b9\u6848\uff0c\u5305\u62ec dockerfile\u3001\u7f16\u6392\u5404\u9879\u670d\u52a1\u4f9d\u8d56\u7684 docker-compose.yml \u4ee5\u53ca\u7b80\u6613\u7684 Setup \u811a\u672c\uff1b\u4f60\u53ef\u4ee5\u5728 snibox\/snibox-docker \u4e0b\u8f7d\u5230\uff1a\ngit clone \u8fd9\u91cc\u6211\u4f7f\u7528 Git \u5c06\u8be5\u4ed3\u5e93\u76f4\u63a5\u514b\u9686\uff0c\u65b9\u4fbf\u4e0e\u8fdc\u7aef\u540c\u6b65\u3002\n\u5728 README.md \u6587\u4ef6\u5185\uff0c\u5b83\u63d0\u4f9b\u7684\u542f\u52a8\u547d\u4ee4\u662f\u8fd9\u6837\u7684\uff1a\n.\/bin\/setup .\/bin\/start \u5bf9\u4e8e\u4e0d\u660e\u4e0d\u767d\u7684\u811a\u672c\uff0c\u6211\u5728\u6267\u884c\u4e4b\u524d\u90fd\u6709\u5148\u770b\u4ee3\u7801\u7684\u4e60\u60ef\uff0c\u4ee5\u514d\u9020\u6210\u4e00\u4e9b\u672a\u77e5\u7684\u5f71\u54cd\uff08\u4f8b\u5982\u5b89\u88c5\u7cfb\u7edf\u5168\u5c40\u4f9d\u8d56\u3001\u4fee\u6539\u5916\u90e8\u6587\u4ef6\u7b49\uff09\u3002\n \u81ea\u4ece\u4f7f\u7528 Docker \u4e4b\u540e\uff0c\u5bf9\u6240\u6709\u7684\u4e00\u952e\u811a\u672c\u90fd\u4ea7\u751f\u4e86\u83ab\u540d\u7684\u6050\u60e7\u548c\u6392\u65a5\ud83d\ude02\u3002\n \u4e8e\u662f\u7ecf\u8fc7\u89c2\u5bdf\u53d1\u73b0\uff0cbin\/start \u5185\u7684\u811a\u672c\u53ea\u6709\u4e00\u884c\uff1a\ndocker-compose up \u6ca1\u4ec0\u4e48\u732b\u817b \u2014\u2014 \u4f9d\u7167 docker-compose.yml \u7684\u914d\u7f6e\u542f\u52a8\u5bb9\u5668\u3002\u518d\u6765\u770b bin\/setup\uff1a\n# ... echo &#34;Copy .env.sample to .env:&#34; # ... echo -e &#34;\\nInject secret key:&#34; # ... echo -e &#34;\\nPull images:&#34; # ... echo -e &#34;\\nCreate database:&#34; # ... echo -e &#34;\\nRun migrations:&#34; # ... echo -e &#34;\\n${GREEN}Setup completed!${NC}&#34; \u6211\u6458\u9009\u4e86\u4e00\u90e8\u5206\u5c55\u793a\uff0c\u4ece\u4ee5\u4e0a\u4ee3\u7801\u4e2d\u5927\u6982\u53ef\u5f97\u77e5\uff1a\u8be5\u811a\u672c\u4e3b\u8981\u5e2e\u6211\u4eec\u6267\u884c\u4e86\u4ee5\u4e0b\u4efb\u52a1\uff1a\n \u590d\u5236 .env.sample\uff08\u7c7b\u4f3c Laravel \u7684 .env.example \u6587\u4ef6\uff09\u5230 .env\u3002 \u5199\u5165 Secret Key\uff08\u7c7b\u4f3c Laravel \u7684 php artisan key:generate \u547d\u4ee4\uff09\u3002 \u62c9\u53d6 Docker \u955c\u50cf\u3002 \u521b\u5efa\u6570\u636e\u5e93\u5e76\u6267\u884c\u8fc1\u79fb\uff08\u7c7b\u4f3c Laravel \u7684 php artisan migrate\uff09\u3002  \u770b\u8d77\u6765\u8fd8\u662f\u5341\u5206\u6709\u5e2e\u52a9\u7684\uff0c\u867d\u7136\u6211\u89c9\u5f97\u5199\u6210\u8f85\u52a9\u811a\u672c\u4e0d\u5408\u9002\uff0c\u800c\u5e94\u8be5\u6253\u5305\u5728 Docker \u955c\u50cf\u5185\u3002\n\u6700\u540e\uff0c\u518d\u6765\u770b\u770b docker-compose.yml\uff0c\u6700\u9700\u8981\u6ce8\u610f\u7684\u662f\uff1a\nservices: frontend: image: snibox\/nginx-puma:1.13.8 ports: - &#34;8000:80&#34; # \u5c06\u955c\u50cf\u5185 80 \u7aef\u53e3\u6620\u5c04\u5230\u5bbf\u4e3b\u673a 8000 \u7aef\u53e3 # ... \u53ef\u901a\u8fc7\u4fee\u6539 8000 \u4e3a\u5176\u5b83\u503c\u6765\u6539\u53d8 Snibox \u7684\u8bbf\u95ee\u7aef\u53e3\uff0c\u6ce8\u610f\u907f\u514d\u51b2\u7a81\u3002\n\u6700\u540e\uff0c\u6211\u4eec\u9700\u8981\u505a\u7684\u5c31\u662f\u6267\u884c\u914d\u7f6e\u811a\u672c\u5e76\u542f\u52a8\u5373\u53ef\u3002\nbin\/setup docker-compose up \u4e2a\u4eba\u66f4\u52a0\u503e\u5411\u4e8e\u4f7f\u7528\u539f\u751f\u7684 docker-compose up\uff0c\u5982\u9700\u540e\u53f0\u8fd0\u884c\uff0c\u5219\u643a\u5e26 -d \u9009\u9879\u5373\u53ef\u3002\n\u7ed3\u8bed \u8be5\u4ed3\u5e93\u6682\u65f6\u8fd8\u5b58\u5728\u4e00\u4e9b\u5c0f\u95ee\u9898\uff0c\u76ee\u524d\u6211\u5df2\u7ecf\u63d0\u4ea4 PR\uff1a\n Move &amp;ldquo;docker-compose pull&amp;rdquo; up. Fix wrong commands, support pass through arguments. ","permalink":"https:\/\/wi1dcard.dev\/posts\/self-hosted-snippet-service\/","summary":"<p><a href=\"https:\/\/github.com\/snibox\/snibox\" target=\"_blank\">snibox\/snibox<\/a> \u662f\u4e00\u6b3e\u4f7f\u7528 Ruby on Rails + Vuex \u7f16\u5199\u7684\u4ee3\u7801\u7247\u6bb5\u6258\u7ba1\u670d\u52a1\u3002\u5bf9\u4e8e\u4e00\u7ebf\u7a0b\u5e8f\u5458\u6765\u8bf4\uff0c\u7ecf\u5e38\u4f1a\u63a5\u89e6\u5230\u5927\u91cf\u7684\u4ee3\u7801\u7247\u6bb5\uff08Snippet\uff09\uff0c\u4e0a\u4f20\u5230 Gist \u65e0\u6cd5\u5b8c\u5168 Private\uff0c\u800c Snibox \u5219\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\u3002<\/p>","title":"\u52a8\u624b\u642d\u5efa\u4ee3\u7801\u7247\u6bb5\u6258\u7ba1\u670d\u52a1"},{"content":"soimort\/you-get \u548c iawia002\/annie \u662f\u4e24\u6b3e\u5341\u5206\u4e0d\u9519\u7684\u547d\u4ee4\u884c\u89c6\u9891\u4e0b\u8f7d\u5de5\u5177\uff0c\u652f\u6301\u5927\u91cf\u7b2c\u4e09\u65b9\u89c6\u9891\u7ad9\u3002\n\u8fd8\u8bb0\u5f97\u591a\u5e74\u524d\u4f7f\u7528 Windows \u7684\u65f6\u5019\uff0c\u7ef4\u68e0\u3001\u7855\u9f20\u7b49\u7b49\u89c6\u9891\u4e0b\u8f7d\u5668\u4eab\u8a89\u76db\u540d\uff0c\u5728\u5708\u5b50\u5185\u65e0\u4eba\u4e0d\u77e5\u65e0\u4eba\u4e0d\u6653\u3002\n\u540e\u6765\u968f\u7740\u56fd\u5185\u4e00\u5927\u6279\u7c7b\u4f3c 56 \u7b49\u89c6\u9891\u7f51\u7ad9\u7684\u5012\u95ed\uff0c\u4ee5\u53ca\u7248\u6743\u653f\u7b56\u539f\u56e0\uff0c\u5f88\u591a\u4e0b\u8f7d\u8f6f\u4ef6\u5f7b\u5e95\u505c\u6b62\u66f4\u65b0\u3002\u539f\u672c\u90a3\u4e9b\u7528\u7535\u8111\u770b\u89c6\u9891\u7684\u7528\u6237\uff0c\u4e5f\u6162\u6162\u6d41\u5411\u4e86\u624b\u673a\u3001\u667a\u80fd\u7535\u89c6\u3002\n\u521a\u521a\u53bb\u5b98\u7f51\u67e5\u770b\u8fd9\u4e24\u6b3e\u8f6f\u4ef6\u7684\u66f4\u65b0\u72b6\u6001\uff0c\u7ef4\u68e0\u505c\u7559\u5728 \u7248\u672c\uff1a2.1.4.1 \uff082017\u5e7411\u670801\u65e5\uff09\uff0c\u7855\u9f20\u505c\u7559\u5728 \u7248\u672c\u53f7: 0.4.8.1 [2017-07-30]\uff0c\u771f\u53ef\u8c13\u65f6\u4ee3\u7684\u5370\u8bb0\u554a\u3002\n\u540e\u6765\u8fc1\u79fb\u5230 macOS\uff0c\u867d\u8bf4\u56fe\u65b9\u4fbf\u7ecf\u5e38\u76f4\u63a5\u624b\u673a\u770b\u89c6\u9891\uff0c\u6709\u65f6\u8fd8\u662f\u6709\u300c\u4e0b\u8f7d\u300d\u7684\u9700\u6c42\u7684\uff08\u6bd4\u5982\u67d0\u4e9b\u770b\u8d77\u6765\u5c31\u4f1a\u88ab\u67e5\u6c34\u8868\u7684\u89c6\u9891\ud83e\udd14\uff09\u3002\u5728\u6478\u722c\u6eda\u6253\u4e2d\u627e\u5230\u4e86 you-get \u548c annie \u8fd9\u4e24\u6b3e\u5f00\u6e90\u7684\u89c6\u9891\u4e0b\u8f7d\u5de5\u5177\uff0c\u5206\u522b\u4f7f\u7528 Python \u548c Go \u8bed\u8a00\u7f16\u5199\u3002\n\u4e24\u6b3e\u5de5\u5177\u5747\u53ef\u901a\u8fc7 Homebrew \u8fdb\u884c\u5b89\u88c5\uff1a\nbrew install you-get brew install annie \u540e\u8005\u57fa\u4e8e Go\uff0c\u5b89\u88c5\u4e8c\u8fdb\u5236\u5305\u65f6\u96f6\u4f9d\u8d56\uff0c\u975e\u5e38\u5feb\u3002\u4f60\u53ef\u4ee5\u901a\u8fc7 brew info &lt;formula&gt; \u6765\u67e5\u770b\u8be6\u7ec6\u4fe1\u606f\u3002\n\u8fd9\u4e24\u6b3e\u5de5\u5177\u6700\u300c\u65e0\u969c\u788d\u300d\u7684\u8bbe\u8ba1\u662f\uff1a\u65e0\u9700\u601d\u8003\u4efb\u4f55\u53c2\u6570\uff0c\u76f4\u63a5\u4e22\u4e00\u4e2a\u94fe\u63a5\u5c31\u80fd\u4e0b\u8f7d\u3002\nyou-get &lt;url&gt; annie &lt;url&gt; \u5bf9\u4e8e\u4e34\u65f6\u4f7f\u7528\u7684\u5de5\u5177\u6027\u9879\u76ee\u6765\u8bf4\uff0c\u6211\u89c9\u5f97\u8fd9\u662f\u4e2a\u5f88\u4f1f\u5927\u7684\u8bbe\u8ba1\uff1b\u80fd\u591f\u8ba9\u7528\u6237\u4e0d\u770b\u6587\u6863\u3001\u300c\u65e0\u8111\u5730\u300d\u987a\u7740\u81ea\u5df1\u65e5\u5e38\u7684\u601d\u7ef4\u5373\u53ef\u76f4\u63a5\u4f7f\u7528\u3002\n\u81f3\u4e8e\u652f\u6301\u7684\u7f51\u7ad9\uff0c\u9879\u76ee\u4e3b\u9875\u53ef\u4f9b\u53c2\u8003\uff1a\n youget - supported-sites annie - supported-sites  \u6700\u540e\uff0c\u4e24\u5de5\u5177\u5747\u63d0\u4f9b\u5f3a\u5927\u7684\u53ef\u9009\u9879\uff0c\u751a\u81f3\u652f\u6301\u81ea\u52a8\u8f6c\u6362\u683c\u5f0f\uff0c\u611f\u5174\u8da3\u7684\u8bdd\u53bb\u770b\u770b\u6587\u6863\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/cli-video-downloader\/","summary":"<p><a href=\"https:\/\/github.com\/soimort\/you-get\" target=\"_blank\">soimort\/you-get<\/a> \u548c <a href=\"https:\/\/github.com\/iawia002\/annie\" target=\"_blank\">iawia002\/annie<\/a> \u662f\u4e24\u6b3e\u5341\u5206\u4e0d\u9519\u7684\u547d\u4ee4\u884c\u89c6\u9891\u4e0b\u8f7d\u5de5\u5177\uff0c\u652f\u6301\u5927\u91cf\u7b2c\u4e09\u65b9\u89c6\u9891\u7ad9\u3002<\/p>","title":"\u5728\u547d\u4ee4\u884c\u4e0b\u8f7d\u7b2c\u4e09\u65b9\u7f51\u7ad9\u7684\u89c6\u9891"},{"content":"tldr-pages\/tldr-cpp-client \u662f tldr-pages\/tldr \u7684 C++ \u5ba2\u6237\u7aef\u5b9e\u73b0\u3002\u540e\u8005\u6536\u96c6\u4e86\u4e00\u7cfb\u5217\u7b80\u5316\u7248\u672c\u7684\u547d\u4ee4\u8bf4\u660e\u624b\u518c\uff0c\u7528\u4e8e\u66ff\u4ee3 man \u547d\u4ee4\uff1b\u4e14\u9879\u76ee\u7531\u793e\u533a\u9a71\u52a8\uff0c\u4e5f\u5c31\u662f\u8bf4\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u63d0\u4ea4 PR \u6765\u5b8c\u5584\u5b83\u3002\nnvbn\/thefuck \u662f\u4e00\u6b3e\u57fa\u4e8e Python \u7f16\u5199\u7684\u547d\u4ee4\u884c\u5de5\u5177\uff0c\u53ef\u5feb\u901f\u4fee\u6b63\uff08\u6ce8\u610f\u4e0d\u662f\u4fee\u590d\uff09\u524d\u4e00\u6761\u547d\u4ee4\u7684\u7528\u6cd5\u9519\u8bef\uff0c\u4f7f\u62a5\u9519\u7684\u547d\u4ee4\u80fd\u591f\u6b63\u5e38\u8fd0\u884c\u3002\n\u8fd9\u4e24\u6b3e\u5de5\u5177\u5206\u522b\u63d0\u4f9b\u4e86 tldr \u548c fuck \u547d\u4ee4\u3002\ntldr  \u5173\u4e8e TL;DR \u7684\u542b\u4e49\u53c2\u89c1 \u672c\u6587\u3002\n \u7528\u8fc7 man \u547d\u4ee4\u7684\u4eba\uff0c\u5e94\u8be5\u8fd8\u8bb0\u5f97\u88ab\u6ee1\u5c4f\u9009\u9879\u4ee5\u53ca\u96f6\u9ad8\u4eae\u652f\u914d\u7684\u6050\u60e7\u5427&hellip;\n\u4f8b\u5982 man tar\uff0c\u4f60\u4e0d\u5f97\u4e0d\u8bfb\u5b8c\u51e0\u4e4e\u6240\u6709\u53c2\u6570\u624d\u77e5\u9053\u300c\u5982\u4f55\u89e3\u538b\u4e00\u4e2a\u538b\u7f29\u5305\u300d\uff0c\u6216\u662f\u9009\u62e9\u6253\u5f00 Google \u641c\u7d22\u3002\n\u5bf9\u4e8e\u9700\u8981\u7cbe\u786e\u8c03\u53c2\u7684\u573a\u666f\uff0cman \u63d0\u4f9b\u7684\u8be6\u7ec6\u8bf4\u660e\u786e\u5b9e\u662f\u5b9e\u7528\u7684\u53c2\u8003\uff0c\u4f46\u591a\u6570\u60c5\u51b5\u6211\u4eec\u53ea\u662f\u60f3\u8981\u7b80\u5355\u5730\u5b8c\u6210\u67d0\u4e2a\u5e38\u89c1\u4efb\u52a1\uff0c\u518d\u53bb Google \u5b9e\u5728\u662f\u592a\u6d6a\u8d39\u65f6\u95f4\uff0c\u6709\u6ca1\u6709\u4ec0\u4e48\u529e\u6cd5\u80fd\u591f\u5728\u7ec8\u7aef\u300c\u4e00\u7ad9\u5f0f\u300d\u641e\u5b9a\u5462\uff1f\u6765\u8bd5\u8bd5 tldr \u5427\uff1a\n\u7b80\u5355\u660e\u4e86\u7684\u5b9e\u8df5\u4f8b\u5b50\uff01\u5373\u4fbf\u518d\u53bb\u770b man tar \u4e5f\u80fd\u591f\u6709\u9488\u5bf9\u6027\u5730\u9605\u8bfb\u4e00\u4e9b\u5e38\u7528\u7684\u9009\u9879\u3002\n\u8be5\u624b\u518c\u5728 GitHub \u6709\u4f17\u591a\u8bed\u8a00\u7684\u5ba2\u6237\u7aef\u5b9e\u73b0\u3002\u6211\u9009\u62e9\u7684\u662f C++ \u7248\u672c\uff0c\u539f\u56e0\u6709\u4e8c\uff1a\u5b98\u65b9\u7ef4\u62a4\uff0c\u4e14\u51e0\u4e4e\u80fd\u591f\u5728\u4efb\u4f55\u673a\u5668\u4e0a\u7f16\u8bd1\u4f7f\u7528\u3002\u5728 macOS \u4e2d\uff0c\u4f7f\u7528 Brew \u5b89\u88c5\u5373\u53ef\uff1a\nbrew install tldr \u4f60\u4e5f\u53ef\u4ee5\u53c2\u8003\u9879\u76ee\u4e3b\u9875\u9009\u62e9\u9002\u5408\u4f60\u7684\u7248\u672c\u3002\nfuck \u5148\u770b\u56fe\uff1a\n\u5c45\u7136\u8fd8\u6709\u8fd9\u79cd\u4e1c\u897f\u7684\u5b58\u5728\uff1f\uff01\u5728\u6211\u542c\u8bf4\u8be5\u9879\u76ee\u7684\u65f6\u5019\u771f\u7684\u60ca\u5446\u4e86\ud83d\ude02\u3002\n\u8be5\u5de5\u5177\u652f\u6301\u7684\u547d\u4ee4\u975e\u5e38\u591a\uff0c\u5728\u9879\u76ee\u4e3b\u9875\u5c55\u793a\u4e86\u5f88\u957f\u7684\u4f8b\u5b50\u548c\u5217\u8868\uff1b\u540c\u65f6\uff0c\u4f60\u8fd8\u53ef\u4ee5\u521b\u5efa\u81ea\u5df1\u7684\u4fee\u6b63\u89c4\u5219\uff0c\u53ea\u9700\u51e0\u884c Python \u4ee3\u7801\u5373\u53ef\u3002\n\u9700\u8981\u6ce8\u610f\u7684\u4e00\u70b9\u662f\uff0cmacOS \u4e2d\u4f7f\u7528 Brew \u5b89\u88c5\u540e\u9700\u8bbe\u7f6e\u522b\u540d\uff1a\nbrew install thefuck echo &#39;eval $(thefuck --alias)&#39; &gt;&gt; .bash_profile # \u6216 .bashrc \/ .zshrc \u7b49 \u6216\u4f7f\u7528\u5176\u5b83\u522b\u540d\u4ee3\u66ff fuck\uff1a\necho &#39;eval $(thefuck --alias f)&#39; &gt;&gt; .bash_profile \u968f\u540e\u518d\u78b0\u5230\u62a5\u9519\uff0c\u5c1d\u8bd5\u4e0b fuck \u5e26\u6765\u7684\u300c\u5fc3\u7406\u300d\u548c\u300c\u8eab\u4f53\u300d\u4e0a\u7684\u53cc\u91cd\u723d\u5feb\u5427\uff1a\n$ Error ... WTF??? fuck! $ ... Finished! 2333\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/tldr-and-the-fuck-in-terminal\/","summary":"<p><a href=\"https:\/\/github.com\/tldr-pages\/tldr-cpp-client\" target=\"_blank\">tldr-pages\/tldr-cpp-client<\/a> \u662f <a href=\"https:\/\/github.com\/tldr-pages\/tldr\" target=\"_blank\">tldr-pages\/tldr<\/a> \u7684 C++ \u5ba2\u6237\u7aef\u5b9e\u73b0\u3002\u540e\u8005\u6536\u96c6\u4e86\u4e00\u7cfb\u5217\u7b80\u5316\u7248\u672c\u7684\u547d\u4ee4\u8bf4\u660e\u624b\u518c\uff0c\u7528\u4e8e\u66ff\u4ee3 <code>man<\/code> \u547d\u4ee4\uff1b\u4e14\u9879\u76ee\u7531\u793e\u533a\u9a71\u52a8\uff0c\u4e5f\u5c31\u662f\u8bf4\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u63d0\u4ea4 PR \u6765\u5b8c\u5584\u5b83\u3002<\/p>\n<p><a href=\"https:\/\/github.com\/nvbn\/thefuck\" target=\"_blank\">nvbn\/thefuck<\/a> \u662f\u4e00\u6b3e\u57fa\u4e8e Python \u7f16\u5199\u7684\u547d\u4ee4\u884c\u5de5\u5177\uff0c\u53ef\u5feb\u901f\u4fee\u6b63\uff08\u6ce8\u610f\u4e0d\u662f\u4fee\u590d\uff09\u524d\u4e00\u6761\u547d\u4ee4\u7684\u7528\u6cd5\u9519\u8bef\uff0c\u4f7f\u62a5\u9519\u7684\u547d\u4ee4\u80fd\u591f\u6b63\u5e38\u8fd0\u884c\u3002<\/p>","title":"\u547d\u4ee4\u884c\u795e\u5668 - tldr \u548c fuck"},{"content":"\u4e00\u7bc7\u6df1\u5165\u8bb2\u89e3 Encode \/ Hash \/ Cryptography \/ Encrypt \u7684\u597d\u6587\u3002\u8f6c\u81ea\uff1ahttps:\/\/paragonie.com\/blog\/2015\/08\/you-wouldnt-base64-a-password-cryptography-decoded\u3002\nThere&rsquo;s a ton of bad programming and security advice on the Internet. Some of the advice is bad because the author is misinformed, some because it emphasizes precision over clarity and most people wind up lost in the jargon.\nIf you feel that cryptography is a weird, complicated, and slightly intimidating subject for which your feelings might be best described as lukewarm (on a good day), we hope that by the time you finish reading this page, you will have a clear understanding of the terms and concepts people use when this topic comes up.\n Warning: The example snippets on this page are for illustrative purposes. Don&rsquo;t use them in your projects. If you want a real-world example to reference, check out the snippets in our Chief Development Officer&amp;rsquo;s StackOverflow answer instead.\n Basic Cryptography Concepts for Developers Let&rsquo;s start with a basic question: What exactly is a cryptographic feature? In the simplest terms we can muster: Cryptographic features use math to secure an application.\nDigging a little deeper: there are a plethora of cryptography algorithms and they can generally be grouped together based on two criteria:\n How much information must be supplied by the developer? What is the intended goal?  Confidentiality? Integrity? Authenticity? Non-repudiation? Deniability? (These two are opposites.)     Keyless Cryptography (0 keys)  Hash Functions   Secret-Key Cryptography (1 key)  Secret-Key Message Authentication Secret-Key Encryption Authenticated Secret-Key Encryption   Public-Key Cryptography (2 keys)  Shared Secret Key Agreement Digital Signatures    The First Rule of Cryptography: Don&rsquo;t Implement it Yourself Developing cryptography features is best left to the experts. By all means, do feel free to tinker, but don&rsquo;t deploy your experiments in production or share them with other developers who might deploy them in production.\nInstead, use a high-level cryptography library that experts have already vetted. Follow the link to read our PHP cryptography library recommendations.\nThe most simplest algorithm to consider is the cryptographic hash function, which accepts one input and returns a single deterministic fixed-size output.\nhash(&quot;sha256&quot;, &quot;&quot;); \/\/ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 hash(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy dog&quot;); \/\/ d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592  When using a well-designed cryptographic hash function, such as BLAKE2 or SHA256, any change you make to the message will result in a drastically different hash output.\nhash(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy cog&quot;); \/\/ e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be  Simple hash functions are fast and deterministic; if you have any arbitrary message, you can calculate the hash output for that particular message. By themselves, they are mostly useful for error checking or as a building block for other cryptographic primitives, which most developers will not need to develop.\nCryptographic hash functions are one-way data transformations. Although you can easily calculate the hash output (often referred to as a message digest) for any arbitrary message, you cannot easily go from the hash output to the original message.\nSome hash functions (such as MD5) have weaker security guarantees and smaller output sizes. As a result, it&rsquo;s almost trivial to calculate two different messages that will produce the same MD5 hash.\nMost cryptography algorithms aren&rsquo;t as simple as hash functions. As a consequence, they are a lot more useful and can provide security guarantees beyond, &ldquo;Yes, this output can be reproduced from this input.&rdquo;\nConsequently, they typically require two pieces of input: The message and a secret key. A secret key should be a unique string of random bytes that both the sender and intended recipient should know, and nobody else.\nA keyed hash function, such as HMAC, is a special implementation of a hash function that accepts a message and a secret key and produces a Message Authentication Code (MAC).\nhash_hmac(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy dog&quot;, &quot;secret key&quot;); \/\/ 4a513ac60b4f0253d95c2687fa104691c77c9ed77e884453c6a822b7b010d36f hash_hmac(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy cog&quot;, &quot;secret key&quot;); \/\/ ed6b9bc9d64e4c923b2cc19c15fff329f343f30884935c10e617e0fe067adef1 hash_hmac(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy dog&quot;, &quot;secret kez&quot;); \/\/ 291579f3123c3126df04a57f78768b6290df93f979b86af25fecd98a9811da5a hash_hmac(&quot;sha256&quot;, &quot;The quick brown fox jumps over the lazy cog&quot;, &quot;secret kez&quot;); \/\/ 298bb0244ebc987810de3892384bb4663742a540db2b3a875f66b09d068d1f64  Keyed hash functions are more useful than hash functions; only someone with the secret key can calculate a MAC for a given message. Therefore, if you transmit a message and a MAC for a given message, and never transmit the secret key, you can be reasonably sure that the message is authentic.\n Warning: Encryption without message authentication is vulnerable to chosen ciphertext attacks. Please read our whitepaper on Secure Data Encryption in PHP.\n Formally, encryption is the reversible process of transforming of a message (called the plaintext) and a secret key into a seemingly random string of bytes (called the ciphertext). i.e. encrypt($message, $key) should return a unique string of random bytes for a given pair of $message and $key.\nUnfortunately, simple secret-key encryption (also known as ECB mode) is not secure. If you encrypt the same (16-byte, for the popular AES encryption algorithm) block within a message with the same key in ECB mode, the ciphertext will repeat.\nModern secret-key encryption, therefore, actually accepts more than two pieces of information. Beyond the plaintext message and a secret key, they also require a unique Initialization Vector (IV, for CBC mode) or nonce (number to be used once, for CTR mode). The difference between a nonce and IV is subtle.\n None of the code on this page is secure; neither are any of the encryption keys.\n \/** * This code is for example purposes only. DO NOT USE IT. * Use https:\/\/github.com\/defuse\/php-encryption instead * * Demo: http:\/\/3v4l.org\/ih8om *\/ bin2hex( openssl_encrypt( \/* Message: *\/ &quot;The quick brown fox jumps over the lazy dog&quot;, \/* Cipher algorithm and block mode: *\/ 'aes-128-ctr', \/* Encryption key: (don't use weak keys like this ever, it's just an example!): *\/ &quot;\\x01\\x02\\x03\\x04&quot; . &quot;\\x05\\x06\\x07\\x08&quot; . &quot;\\x09\\x0a\\x0b\\x0c&quot; . &quot;\\x0d\\x0e\\x0f\\x10&quot;, \/* Constant that means &quot;don't encode&quot;: *\/ OPENSSL_RAW_DATA, \/* Initialization Vector or Nonce -- don't ever actually use all NULL bytes: *\/ str_repeat(&quot;\\0&quot;, 16) \/\/ This is a really bad way to generate a nonce or IV. ) ); \/\/ 8f99e1315fcc7875325149dda085c504fc157e39c0b7f31c6c0b333136a7a8877c4971a5ce5688f94ae650 \/** * This code is for example purposes only. DO NOT USE IT. * Use https:\/\/github.com\/defuse\/php-encryption instead * * Demo: http:\/\/3v4l.org\/ZgW38 *\/ openssl_decrypt( \/* Message: *\/ hex2bin( &quot;8f99e1315fcc7875325149dda085c504fc157e39c0b7f31c6c0b333136a7a8877c4971a5ce5688f94ae650&quot; ), \/* Cipher algorithm and block mode: *\/ 'aes-128-ctr', \/* Encryption key: (don't use weak keys like this ever, it's just an example!): *\/ &quot;\\x01\\x02\\x03\\x04&quot; . &quot;\\x05\\x06\\x07\\x08&quot; . &quot;\\x09\\x0a\\x0b\\x0c&quot; . &quot;\\x0d\\x0e\\x0f\\x10&quot;, \/* Constant that means &quot;don't encode&quot;: *\/ OPENSSL_RAW_DATA, \/* Initialization Vector or Nonce -- don't ever actually use all NULL bytes: *\/ str_repeat(&quot;\\0&quot;, 16) \/\/ This is a really bad way to generate a nonce or IV. ); \/\/ The quick brown fox jumps over the lazy dog  A more in-depth and less illustrative example (which properly generates IVs) is available here.\nFor a closer examination at symmetric-key encryption with OpenSSL, read our white paper.\nDecryption is only successful if the same IV\/nonce and secret key are used. However, only the key must be kept secret; the IV and nonce can even be broadcast with your encrypted message.\nIf you recall from our earlier blog post, &lt;em&gt;Using Encryption and Authentication Correctly&lt;\/em&gt;, secret-key encryption itself is vulnerable to tampering unless you combine it with authentication.\nThe only strategies proven to be secure are to use an AEAD mode or to always encrypt first then authenticate the encrypted data with a MAC.\nIf you are following an Encrypt-Then-MAC construction, you want to use two separate secret keys: One for the encryption, the other for the MAC. In other words, apply the previous two sections together:\n\/** * This code is for example purposes only. DO NOT USE IT. * Use https:\/\/github.com\/defuse\/php-encryption instead *\/ $nonce = random_bytes(16); $ciphertext = openssl_encrypt( \/* Message: *\/ &quot;The quick brown fox jumps over the lazy dog&quot;, \/* Cipher algorithm and block mode: *\/ 'aes-128-ctr', \/* Encryption key: (don't use weak keys like this ever, it's just an example!) * Instead, you want to generate 16, 24, or 32 random bytes (i.e. random_bytes(16)) * on your own. It's generally a bad idea to copy and paste security code. *\/ &quot;\\x01\\x02\\x03\\x04&quot; . &quot;\\x05\\x06\\x07\\x08&quot; . &quot;\\x09\\x0a\\x0b\\x0c&quot; . &quot;\\x0d\\x0e\\x0f\\x10&quot;, \/* Constants that mean &quot;don't encode&quot; and &quot;we have no padding&quot; to the OpenSSL API: *\/ OPENSSL_RAW_DATA + OPENSSL_ZERO_PADDING, \/* Initialization Vector or Nonce: *\/ $nonce ); \/\/ You should choose a better HMAC key than we did for this article: $mac = hash_hmac(&quot;sha256&quot;, $nonce.$ciphertext, &quot;\\xff\\xfe\\xfd\\xfc&quot; . &quot;\\xfb\\xfa\\xf9\\xf8&quot; . &quot;\\xf7\\xf6\\xf5\\xf4&quot; . &quot;\\xf3\\xf2\\xf1\\xf0&quot;, true); echo bin2hex($nonce.$ciphertext.$mac); \/* 71b5546f 6cb857cd 0d8f8be3 f9312c74 &lt;- Nonce (randomly chosen) 356146df 274552c2 e98d3008 b1dfa35c &lt;- Ciphertext 60d6130d 9c9ca525 6c2f2f25 0b321176 06563174 c3b073a0 5ab263 4d1c7416 b086a316 a0474a05 84e3793c &lt;- MAC a32fde09 0d82a5ef 213cb329 da3b5b06 *\/  It is important to exercise caution when combining cryptographic features. Our basic protocol as written above has no redundant features:\n Secret key encryption provides confidentiality such that it can only be read with the correct secret key. Keyed hash functions provide authentication (and consequently, message integrity) such that anyone possessing the correct secret key can recalculate the same MAC. A random IV\/nonce is used to make each encrypted message unique, even if the unencrypted message is the same.  It should go without saying, but double-encrypting or double-authenticating when you need authenticated encryption would just be silly.\nPublic key cryptography is challenging for nontechnical people to understand, and even more challenging for technical people to explain correctly without burying the reader in mathematics or missing critical points. The end result is usually a lot of confusion and occasionally a false sense of understanding. (A fauxreka moment, if you will.)\nHere&rsquo;s all you need to know right now: Unlike secret key encryption, which involves a single secret key that is held by both parties, in public key cryptography, each participant has two keys:\n Each participant has a private key, which they never share. Each participant also has a public key, which is mathematically related to their private key, which they share with everyone.  It is unfortunate that the &ldquo;key&rdquo; terminology from secret key cryptography stuck when public key cryptography was discovered, as there aren&rsquo;t very many physical systems that are intuitively similar to what&rsquo;s going on here. Some people have attempted to explain public key cryptography using colors or detailed explanations. If you&rsquo;re interested in the intimate details, we recommend both of the links in the previous sentence.\nFor everyone else, if you can accept these premises, understanding the rest isn&rsquo;t hard:\n To use public key cryptography, you generate a key-pair and share the public key, but keep the private key to yourself. (In most cases, every participant does this.) There is only one private key for any given public key. Both of the keys in a given key-pair are related to each other, mathematically. Given a public key, it is almost impossible to figure out what the private key is. Given a private key, you can near-instantly calculate the related public key.  Got it? Let&rsquo;s build something with this understanding.\nLet&rsquo;s say you want to talk to a friend over the Internet using secret key cryptography (which is much faster than public key cryptography), but you don&rsquo;t want anyone else to read it. You and her haven&rsquo;t already agreed upon a secret key. How do you do it?\nGlossing over the finer details (the color video above explains it fairly well), this is what you do:\n You send her your public key (yellow). She sends you her public key (light blue). Combine your private key (green) and her public key (blue) to form a shared secret key. She will combine her private key (red) with your public key (yellow) to form the same exact shared key.  How? Modular arithmetic (classic Diffie Hellman) or multiplication along elliptic curves over finite fields (modern Elliptic Curve Diffie Hellman).\nDigital signature algorithms, such as EdDSA (Edwards-curve Digital Signature Algorithm), are one of the most useful innovations to result from public key cryptography.\nA digital signature is calculated from a message and a private key. Earlier algorithms (such as ECDSA) also required you to generate a unique random nonce for each message, but this was proven to be error-prone in the real world.\nAnyone else with a copy of your public key can verify that a particular message was signed by your private key. Unlike keyed hash functions, this verification takes place without requiring you to reveal your private key.\nCommon Misconceptions and Pitfalls Quick answer: Just use bcrypt. For PHP developers, this means &lt;code&gt;password_hash()&lt;\/code&gt; and &lt;code&gt;password_verify()&lt;\/code&gt; rather than crypt().\nMany developers think passwords should be encrypted, but this is false. Passwords should be hashed, not encrypted. Furthermore, don&rsquo;t confuse password hashing algorithms with simple cryptographic hash functions. They&rsquo;re not the same thing:\nUnlike cryptographic hashes, password hashes require more than one input parameter. But unlike encryption algorithms, password hashes are one-way deterministic trap door calculations. Also unlike secret-key encryption, the salt does not need to remain secret; it merely needs to be unique per user. The purpose of a unique salt per user is to thwart pre-computation and to make brute-force guessing passwords from a list of hashes more expensive.\nCan I encrypt my (bcrypt) password hashes?\nYes. If you run your web application and your database on separate hardware servers, this actually provides a substantial defense in depth. That&rsquo;s the reasoning behind our password_lock library.\nDigital signatures can prove authenticity, cryptographic hash functions can not.\nThere is a nontrivial portion of technical users that will, upon downloading an executable from a website, recalculate the MD5 or SHA1 hash of the file and compare it to one displayed on the web page they downloaded the file from. If it matches, they will execute the file, fully trusting its contents to be genuine.\nIf both the file and the hash value are stored on the same server, this is a completely ludicrous waste of time: Any attacker who can alter your download can replace the hashes on the web page too. (If the file and hash are on separate servers, the situation is a little different, but the improvement is not significant enough to warrant eschewing a better solution.)\nAfter all, as we said above, hash functions like MD5 and SHA1 produce a deterministic fixed-size output for a given input. There are no secrets involved. When a solution does not increase security but makes people feel more secure, we call it security theater.\nCryptographic hash functions are security theater in this situation. You want digital signatures instead.\nTo improve security, instead of posting MD5\/SHA1 hashes, the software vendor can instead sign their package with their EdDSA private key and share their EdDSA public key far and wide. When you download the file, you should also download the signature and, using the verified public key, check that it is authentic.\nFor example: Minisign.\nA keyed hash function won&rsquo;t work here either, as you would need to distribute the secret key in order for anyone to be able to verify the signature. If they have the secret key, they can forge their own signatures for maliciously altered message (in this case, executable file).\nDigital signatures are the best way to achieve assurance about the authenticity of a download. MD5\/SHA1 hashes are almost always useless here.\nA common beginner&rsquo;s mistake is to use an encoding function, such as base64_encode(), to attempt to obfuscate information. Consider the following code, which was offered in a LinkedIn discussion about how to properly store passwords in a PHP web application:\nA lot of developers will either encode or compress information and assume their solution provides the same level of security as actual cryptographic features simply because the output is not human readable. It doesn&rsquo;t.\nEncoding and compression algorithms are both reversible, keyless transformations of information. Encoding specifies how information should be represented in human-readable text. Compression attempts to reduce an input to as little space as possible. Both are useful, but they are not cryptographic features.\n Cryptographic hash algorithms (e.g. SHA256) are deterministic one-way algorithms that require zero keys. Keyed hashing algorithms (e.g. HMAC) are used for authentication in secret-key cryptography; requires one key. Secret-key encryption algorithms (e.g. AES-CTR) are used to transform messages so only someone possessing the secret key can reverse; requires one key. Shared secret agreement algorithms (e.g. ECDH) are used to negotiate a shared secret key while only requiring the public transmission of both party&rsquo;s public keys. Requires four keys (two pairs of private\/public) to generate a fifth. Digital signature algorithms (e.g. Ed25519) are used to sign messages (with one&rsquo;s private key) that anyone possessing the corresponding public key can validate. Requires two keys. Password hashing algorithms (e.g. bcrypt) are slow hashing algorithms designed specifically for being difficult to efficiently attack with a brute force search. Requires one secret input and a per-user salt. Encoding algorithms (e.g. Base64) are not cryptographic. Compression algorithms (e.g. gzip) are not cryptographic.  Keep in Mind  Don&rsquo;t encrypt passwords. Instead, hash them with a password hashing algorithm. (You may encrypt the hashes.) Hash functions like MD5, SHA1, and SHA256 are not encryption. Anyone who uses the phrase &ldquo;password encryption&rdquo; probably needs to read this entire page carefully, because they are deeply mistaken. Secret-key encryption without message authentication is insecure (it&rsquo;s vulnerable to chosen ciphertext attacks). For downloads: digital signatures prove authenticity, hashes do not. You want a Minsign or GPG signature, not an MD5 hash.   We hope that this post serves as a good introduction to cryptography concepts. Our team publishes new posts about cryptography, application security, and web development in PHP anywhere from 2 to 5 times per month (usually on Friday). We also offer code review and technology consulting services.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/you-wouldnt-base64-a-password-cryptography-decoded\/","summary":"<p>\u4e00\u7bc7\u6df1\u5165\u8bb2\u89e3 Encode \/ Hash \/ Cryptography \/ Encrypt \u7684\u597d\u6587\u3002\u8f6c\u81ea\uff1a<a href=\"https:\/\/paragonie.com\/blog\/2015\/08\/you-wouldnt-base64-a-password-cryptography-decoded\">https:\/\/paragonie.com\/blog\/2015\/08\/you-wouldnt-base64-a-password-cryptography-decoded<\/a>\u3002<\/p>","title":"You Wouldn't Base64 a Password - Cryptography Decoded"},{"content":"\u8fd9\u53ef\u80fd\u662f\u622a\u81f3\u76ee\u524d\u6211\u8ba4\u4e3a\u6700\u4f18\u96c5\u7684\u535a\u5ba2\u56fe\u7247\u7ba1\u7406\u65b9\u6848\u6ca1\u6709\u4e4b\u4e00\u3002\n\u80cc\u666f \u65e9\u671f \u6700\u65e9\uff0c\u6211\u7684\u535a\u5ba2\u91c7\u7528\u5355\u53f0 PHP \u670d\u52a1\u5668\u642d\u5efa\u52a8\u6001\u535a\u5ba2\uff0c\u5c06\u56fe\u7247\u5b58\u50a8\u81f3\u670d\u52a1\u5668\u5e76\u5b9a\u671f\u5907\u4efd\u3002\u800c\u8bbf\u5ba2\u5219\u662f\u901a\u8fc7 CDN \u52a0\u901f\uff0c\u4ee5\u4fbf\u5feb\u901f\u8f7d\u5165\u56fe\u7247\u3002\n\u7f3a\u70b9\uff1a\n \u5907\u4efd\u4e0d\u53ca\u65f6\uff0c\u5927\u91cf\u5197\u4f59\u6570\u636e\u3002 \u56fe\u7247\u7ba1\u7406\u64cd\u4f5c\u4e0d\u4fbf\u3002  \u4e2d\u671f \u540e\u6765\uff0c\u5c1d\u8bd5\u6539\u7528\u4e03\u725b OSS + CDN \u5168\u5bb6\u6876\uff0c\u6570\u636e\u91cf\u548c\u6d41\u91cf\u4e0d\u5927\uff0c\u6240\u4ee5\u4e00\u76f4\u5728\u7528\u514d\u8d39\u989d\u5ea6\u3002\u53e6\u5916\uff0c\u622a\u6b62 2018 \u5e74\u7684\u67d0\u4e2a\u6708\uff0c\u65e9\u671f\u6ce8\u518c\u7684\u8001\u7528\u6237\u662f\u4e00\u76f4\u62e5\u6709 \u65e0\u9700\u5907\u6848 \u7684\u65e0\u9650\u5236\u6d4b\u8bd5\u57df\u540d\u7684\uff08\u7136\u800c\u540e\u6765\u5c31\u6536\u5230\u4e86\u5f3a\u5236\u56de\u6536\u7684\u90ae\u4ef6&hellip; \u56fd\u5185\u4f01\u4e1a\u679c\u7136\u4e0d\u53ef\u4fe1\uff09\u3002\n\u7f3a\u70b9\uff1a\n \u4e03\u725b\u514d\u8d39\u670d\u52a1\u771f\u5fc3\u4e0d\u9760\u8c31\uff0c\u56fd\u5916\u8bbf\u95ee\u5de8\u5361\uff0c\u5bfc\u81f4\u6211\u65e5\u5e38\u5728\u5899\u5916\u6d4f\u89c8\u81ea\u5df1\u535a\u5ba2\u90fd\u7279\u522b\u6162\u3002 \u7ba1\u7406\u8d77\u6765\u540c\u6837\u4e0d\u65b9\u4fbf\uff0c\u5907\u4efd\u4e5f\u4e0d\u65b9\u4fbf\u3002\u5bf9\u4e8e\u6211\u8fd9\u4e2a\u6d01\u7656\u5f3a\u8feb\u75c7\u6765\u8bf4\uff0c\u6709\u591a\u4f59 Dangling \u7684\u6587\u4ef6\u5b58\u5728\u7b80\u76f4\u4e0d\u53ef\u9976\u6055\u3002 \u6570\u636e\u653e\u5728\u56fd\u5185\u7684\u7b2c\u4e09\u65b9\u670d\u52a1\uff0c\u8bf4\u4e0d\u5b9a\u54ea\u5929\u6709\u4ec0\u4e48\u8fdd\u89c4\u88ab\u67e5\u6c34\u8868\uff0c\u65b9\u3002  \u540e\u671f \u66f4\u6362\u4e3a Hexo \u540e\uff0c\u4e00\u76f4\u5728\u7528\u5927\u4f6c\u7684\u56fe\u5e8a\uff1asm.ms\u3002\n\u76f4\u5230\u8fd1\u671f\uff0c\u5199\u535a\u5ba2\u65f6\u622a\u56fe\u5b8c\u6bd5\u60f3\u8981\u4e0a\u4f20\uff0c\u5374\u5076\u7136\u53d1\u73b0\u56fe\u5e8a\u9875\u9762\u63d0\u793a\uff1a\u7ef4\u62a4\u5347\u7ea7\u4e2d\uff0c\u8bf7\u7a0d\u540e\u8bbf\u95ee\u3002\n\u63a5\u4e0b\u6765\u5927\u7ea6\u4e00\u6574\u5929\u5de6\u53f3\uff0c\u4e00\u76f4\u5904\u4e8e\u65e0\u6cd5\u4e0a\u4f20\u7684\u72b6\u6001\u3002\u7528\u8fc7\u5404\u79cd\u514d\u8d39\u56fe\u5e8a\u7f51\u76d8\u7684\u6211\u4e0d\u7981\u5185\u5fc3\u4e00\u7d27\uff1a\u96be\u4e0d\u6210\uff0c\u53c8\u662f\u8981\u51c9\u4e86\uff1f\u4e8e\u662f\u8d76\u7d27\u628a\u4e4b\u524d\u4e0a\u4f20\u7684\u6240\u6709\u56fe\u7247\u7edf\u7edf\u6392\u67e5\u4e00\u904d\uff0c\u53d1\u73b0\u53ea\u6709\u6781\u4e2a\u522b\u56fe\u7247\u51fa\u73b0 404\u3002\n\u7f3a\u70b9\uff1a\n \u5982\u4e0a\u6587\u6240\u8bf4\uff0c\u514d\u8d39\u56fe\u5e8a\u4e0d\u5b58\u5728 SLA\uff0c\u53ef\u9760\u6027\u672a\u77e5\uff0c\u867d\u7136 sm.ms \u5927\u4f6c\u5df2\u7ecf\u6491\u4e86\u5f88\u4e45\uff0c\u4e5f\u76f8\u5bf9\u6bd4\u8f83\u9760\u8c31\uff0c\u4f46\u8fd8\u662f\u4e0d\u653e\u5fc3\u3002 \u6bcf\u6b21\u622a\u56fe\u5b8c\u6bd5\u8fd8\u9700\u8981\u4e0a\u4f20\uff0c\u9ebb\u70e6\u3002  \u867d\u7136\u76ee\u524d\u57fa\u672c\u672a\u53d7\u5230\u5f71\u54cd\uff0c\u4f46\u5374\u8ba9\u6211\u5ffd\u7136\u8b66\u9192 \u2014\u2014 \u6216\u8bb8\u662f\u65f6\u5019\u5c1d\u8bd5\u4e00\u4e0b\u4e0d\u4f7f\u7528\u5916\u90e8\u56fe\u5e8a\u4e86\u3002\n\u65b9\u6848 \u57fa\u672c\u601d\u8def\u5982\u4e0b\uff0c\u5927\u81f4\u5206\u4e3a\u4e24\u90e8\u5206\uff1a\n\u5b58\u50a8\uff08Git-LFS\uff09 \u6839\u636e\u4ee5\u4e0a\u95ee\u9898\uff0c\u9996\u5148\u9700\u8981\u89e3\u51b3\u7684\u5c31\u662f\u5982\u4f55\u5b58\u50a8\u3002\u76f4\u63a5\u4fdd\u5b58\u5728 Git Repo \u5185\u80af\u5b9a\u4e0d\u5408\u9002\u3002Git \u65e0\u6cd5 Diff \u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u5982\u679c\u5728\u535a\u5ba2\u66f4\u65b0\u548c\u91cd\u6784\u8fc7\u7a0b\u4e2d\u4f18\u5316\u3001\u4fee\u6539\u3001\u79fb\u52a8\u8fd9\u4e9b\u56fe\u7247\u6587\u4ef6\uff0c\u90a3\u5bf9\u4e8e Git \u4ed3\u5e93\u6765\u8bf4\u5c06\u662f\u300c\u7206\u70b8\u6027\u300d\u7684\uff0c\u4f60\u4f1a\u770b\u5230\u4ed3\u5e93\u5927\u5c0f\u6210\u500d\u589e\u957f\uff0cCI\/CD \u6267\u884c Clone \u548c Build \u65f6\u4f1a\u4e25\u91cd\u62d6\u6162\u901f\u5ea6\u3002\u867d\u7136\u6709\u65b9\u6cd5\u53ef \u540e\u671f\u6e05\u7406\uff0c\u4f46\u6211\u5e76\u4e0d\u559c\u6b22\u8fd9\u79cd\u602a\u5f02\u7684\u6298\u4e2d\u65b9\u6848\uff0c\u9664\u975e\u4ed3\u5e93\u5df2\u7ecf\u88ab\u4e8c\u8fdb\u5236\u6587\u4ef6\u300c\u6c61\u67d3\u300d\u3002\n\u9488\u5bf9\u8fd9\u4e2a\u95ee\u9898\uff0cGit-LFS \u662f\u4e2a\u4e0d\u9519\u7684\u89e3\u51b3\u65b9\u6848\u3002\u5b83\u662f\u4e00\u4e2a Git \u63d2\u4ef6\uff0c\u662f\u7531 GitHub \u800c\u975e Git \u5b98\u65b9\u63a8\u51fa\uff0c\u5c3d\u7ba1\u5b98\u7f51\u98ce\u683c\u7684\u786e\u5f88\u50cf\ud83d\ude02\u3002\n\u8be5\u9879\u76ee\u7684\u57fa\u672c\u539f\u7406\u5f88\u7b80\u5355\uff0c\u5728\u672c\u5730 Git \u4e0a\u5b89\u88c5\u4e00\u7cfb\u5217 Hooks\uff0c\u901a\u8fc7\u94a9\u5b50\u300c\u62e6\u622a\u300d\u5404\u7c7b\u64cd\u4f5c\uff0c\u4f8b\u5982 Push \/ Pull \/ Checkout\u3002\u5728\u6267\u884c\u8fd9\u4e9b\u64cd\u4f5c\u65f6\uff0c\u81ea\u52a8\u4ece Git-LFS \u670d\u52a1\u5668\u4e0b\u8f7d\u7531\u5176\u7ba1\u7406\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u3002\n\u5728\u771f\u6b63\u7684 Git \u4ed3\u5e93\u5185\uff0c\u5b9e\u9645\u4e0a\u53ea\u4fdd\u7559\u8be5\u4e8c\u8fdb\u5236\u6587\u4ef6\u7684\u54c8\u5e0c\u7b49\u6570\u636e\u3002\u800c\u5b9e\u5b9e\u5728\u5728\u7684\u6587\u4ef6\u6570\u636e\u5b58\u50a8\u5728 Git-LFS \u670d\u52a1\u5668\u5185\uff0c\u5728\u9700\u8981\u7684\u65f6\u5019\u624d\u4e0b\u8f7d\u3002\u8fd9\u6837\u65e2\u8282\u7701\u4ed3\u5e93\u7684\u5b58\u50a8\u7a7a\u95f4\uff0c\u53e6\u4e00\u65b9\u9762\u4e5f\u80fd\u8282\u7701\u4f60\u7684\u65f6\u95f4\u548c\u5e26\u5bbd\u3002\n\u5b89\u88c5\u4f7f\u7528\u6781\u5176\u7b80\u5355\uff0c\u4ee5 macOS \u4e3a\u4f8b\uff1a\nbrew install git-lfs git lfs install # \u5b89\u88c5 Hooks cd your-repo \u544a\u77e5 LFS \u8ffd\u8e2a\u67d0\u4e9b\u6587\u4ef6\uff0c\u53ef\u4f7f\u7528\u7c7b\u4f3c .gitignore \u6587\u4ef6\u5185\u7684 glob \u8bed\u6cd5\uff0c\u4ee5 *.png \u4e3a\u4f8b\uff1a\ngit lfs track &#34;*.png&#34; \u4ee5\u4e0a\u547d\u4ee4\u4f1a\u521b\u5efa .gitattributes \u6587\u4ef6\uff0c\u4e0d\u8981\u5220\u9664\u5b83\uff0c\u5e76\u786e\u4fdd\u63d0\u4ea4\u5230\u4ed3\u5e93\u5185\u3002\n\u597d\u4e86\uff0c\u63a5\u4e0b\u6765\u6b63\u5e38\u6267\u884c\u5176\u5b83 Git \u64cd\u4f5c\u5373\u53ef\u3002Push \u5230 GitHub \u540e\uff0c\u5728 Web \u9875\u9762\u6253\u5f00\u4f60\u7684\u6587\u4ef6\uff0c\u53ef\u770b\u5230\u4ee5\u4e0b\u5b57\u6837\uff1a\n Stored with Git LFS\n \u8bf4\u660e\u6587\u4ef6\u5df2\u7ecf\u88ab Git-LFS \u63a5\u7ba1\u5e76\u5b58\u50a8\u5566\u3002\n\u6700\u540e\uff0c\u9700\u8981\u6ce8\u610f\u4e00\u70b9\uff1a\u7531\u4e8e Git-LFS \u662f\u4e00\u4e2a\u300c\u7b2c\u4e09\u65b9\u6807\u51c6\u4e0e\u5b9e\u73b0\u300d\uff0c\u6545\u5e76\u4e0d\u662f\u6240\u6709 Git \u670d\u52a1\u90fd\u652f\u6301 LFS \u5b58\u50a8\u3002\n\u65b0\u589e\uff08Shell \u811a\u672c\uff09 \u6211\u5e73\u65f6\u4f7f\u7528 macOS \u81ea\u5e26\u7684 Screenshot \u5de5\u5177\uff0c\u4e0e\u591a\u6570\u622a\u56fe\u5de5\u5177\u7c7b\u4f3c\uff0c\u5b83\u53ef\u4ee5\u5c06\u56fe\u7247\u5b58\u50a8\u81f3\u526a\u8d34\u677f\u3002\u90a3\u4e48\uff0c\u5982\u4f55\u5feb\u901f\u5c06\u526a\u8d34\u677f\u5185\u7684\u56fe\u7247\u8f93\u51fa\u4e3a\u6587\u4ef6\uff0c\u4e14\u6309\u7167\u4e00\u5b9a\u683c\u5f0f\u7ec4\u7ec7\u6587\u4ef6\u540d\u5462\uff1f\u8fd9\u9700\u8981\u4e00\u70b9\u5c0f\u6280\u5de7\u3002\n\u63a8\u8350\u4e00\u4e2a\u540d\u4e3a jcsalterego\/pngpaste \u7684\u5c0f\u5de5\u5177\uff0c\u987e\u540d\u601d\u4e49\uff0c\u5b83\u5c31\u50cf macOS \u4e0b\u7684 pbpaste \u4e00\u6837\uff0c\u53ef\u4ee5\u5728\u7ec8\u7aef\u5feb\u901f\u8bfb\u53d6\u526a\u8d34\u677f\u5e76\u5bfc\u51fa\uff0c\u6b63\u5982\u5728\u9879\u76ee\u9996\u9875\u4e0a\u63cf\u8ff0\u7684\u90a3\u6837\uff1a\n Paste PNG into files, much like pbpaste does for text.\n \u63a5\u4e0b\u6765\uff0c\u6211\u9700\u8981\u4e00\u4e2a\u300c\u5c0f\u811a\u672c\u300d\uff0c\u8fdb\u884c\u4e00\u70b9\u5305\u88c5\u5de5\u4f5c\uff0c\u6211\u5c06\u5b83\u4fdd\u5b58\u4e3a .\/image.sh\uff1b. \u4e3a Hexo \u535a\u5ba2\u7684\u6839\u76ee\u5f55\uff0c\u4e0b\u540c\u3002\n#!\/bin\/bash -eu  dir=$(dirname $0) # \u8be5\u811a\u672c\u6240\u5728\u76ee\u5f55\uff0c\u7528\u4e8e\u5b9a\u4f4d\u56fe\u7247\u5b58\u50a8\u8def\u5f84\uff0c\u53ef\u66ff\u6362\u4e3a\u5176\u5b83 tmp_file=$(mktemp) # \u751f\u6210\u4e34\u65f6\u6587\u4ef6\u8def\u5f84 pngpaste $tmp_file # \u5c06\u526a\u8d34\u677f\u56fe\u7247\u4fdd\u5b58\u81f3\u4e34\u65f6\u6587\u4ef6 hash=$(md5 &lt; $tmp_file) # \u8ba1\u7b97\u56fe\u7247\u7684\u54c8\u5e0c\u503c\uff0c\u7528\u4e8e\u552f\u4e00\u6587\u4ef6\u540d img=&#34;\/images\/$hash.png&#34; # \u62fc\u63a5\u56fe\u7247 URI mv $tmp_file &#34;$dir\/source$img&#34; # \u5c06\u4e34\u65f6\u6587\u4ef6\u79fb\u52a8\u4e3a\u6700\u7ec8\u56fe\u7247\u6587\u4ef6 echo &#34;![]($img)&#34; | tee &gt;(pbcopy) # \u751f\u6210 Markdown \u683c\u5f0f\u7684\u56fe\u7247\u94fe\u63a5\uff0c\u8f93\u51fa\u81f3 STDOUT \u540c\u65f6\u5199\u5165\u526a\u8d34\u677f \u641e\u5b9a\u3002\u6b64\u5904\u4e0d\u91c7\u7528\u62fc\u63a5\u65f6\u95f4\u6216\u968f\u673a\u5b57\u7b26\u4e32\uff0c\u800c\u662f\u54c8\u5e0c\u503c\u4f5c\u4e3a\u6587\u4ef6\u540d\u7684\u539f\u56e0\uff0c\u662f\u4e3a\u4e86\u4fdd\u8bc1\u5e42\u7b49\u6027\u3002\n\u6700\u7ec8\u6548\u679c\u4e3a\uff0c\u622a\u56fe\u8f6f\u4ef6\u622a\u5c4f\uff0c\u7ec8\u7aef\u5185\u8fd0\u884c .\/image.sh \u5373\u53ef\u5c06\u526a\u8d34\u677f\u5185\u7684\u56fe\u7247\u4fdd\u5b58\u4e3a .\/source\/images\/$hash.png\uff0c\u7b80\u5355\u5230\u51e0\u4e4e\u4e0d\u80fd\u518d\u7b80\u5355\u3002\n\u5b8c\u7f8e\u89e3\u51b3 Git \u4ed3\u5e93\u5927\u5c0f\u95ee\u9898\u3001\u4e0a\u4f20\u9ebb\u70e6\u95ee\u9898\uff1b\u6700\u91cd\u8981\u7684\u662f\uff0c\u56fe\u7247\u7ba1\u7406\u4e0e\u672c\u5730\u6587\u4ef6\u64cd\u4f5c\u65e0\u5f02\uff08\u5b9e\u9645\u5c31\u662f\u5728\u64cd\u4f5c\u672c\u5730\u6587\u4ef6\ud83d\ude02\uff09\uff0c\u65e0\u7f1d\u4f7f\u7528\u5404\u7c7b\u547d\u4ee4\u6216 GUI\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/manage-blog-images-with-git-lfs\/","summary":"<p>\u8fd9\u53ef\u80fd\u662f\u622a\u81f3\u76ee\u524d\u6211\u8ba4\u4e3a\u6700\u4f18\u96c5\u7684\u535a\u5ba2\u56fe\u7247\u7ba1\u7406\u65b9\u6848\u6ca1\u6709\u4e4b\u4e00\u3002<\/p>","title":"\u4f7f\u7528 Git-LFS + \u4e00\u70b9\u6280\u5de7\u7ba1\u7406\u535a\u5ba2\u56fe\u7247"},{"content":"\u641c\u96c6\u4e00\u4e9b GitHub \u5e38\u89c1\u9a9a\u7f29\u5199\uff0c\u4ee5\u5907\u67e5\u8be2\u4f7f\u7528\u3002\n \u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/farer.org\/2017\/03\/01\/code-review-acronyms\/\n  PR: Pull Request. \u62c9\u53d6\u8bf7\u6c42\uff0c\u7ed9\u5176\u4ed6\u9879\u76ee\u63d0\u4ea4\u4ee3\u7801 LGTM: Looks Good To Me. \u6715\u77e5\u9053\u4e86 \u4ee3\u7801\u5df2\u7ecf\u8fc7 review\uff0c\u53ef\u4ee5\u5408\u5e76 SGTM: Sounds Good To Me. \u548c\u4e0a\u9762\u90a3\u53e5\u610f\u601d\u5dee\u4e0d\u591a\uff0c\u4e5f\u662f\u5df2\u7ecf\u901a\u8fc7\u4e86 review \u7684\u610f\u601d WIP: Work In Progress. \u4f20\u8bf4\u4e2d\u63d0 PR \u7684\u6700\u4f73\u5b9e\u8df5\u662f\uff0c\u5982\u679c\u4f60\u6709\u4e2a\u6539\u52a8\u5f88\u5927\u7684 PR\uff0c\u53ef\u4ee5\u5728\u5199\u4e86\u4e00\u90e8\u5206\u7684\u60c5\u51b5\u4e0b\u5148\u63d0\u4ea4\uff0c\u4f46\u662f\u5728\u6807\u9898\u91cc\u5199\u4e0a WIP\uff0c\u4ee5\u544a\u8bc9\u9879\u76ee\u7ef4\u62a4\u8005\u8fd9\u4e2a\u529f\u80fd\u8fd8\u672a\u5b8c\u6210\uff0c\u65b9\u4fbf\u7ef4\u62a4\u8005\u63d0\u524d review \u90e8\u5206\u63d0\u4ea4\u7684\u4ee3\u7801\u3002 PTAL: Please Take A Look. \u4f60\u6765\u7785\u7785\uff1f\u7528\u6765\u63d0\u793a\u522b\u4eba\u6765\u770b\u4e00\u4e0b TBR: To Be Reviewed. \u63d0\u793a\u7ef4\u62a4\u8005\u8fdb\u884c review TL;DR: Too Long; Didn&rsquo;t Read. \u592a\u957f\u61d2\u5f97\u770b\u3002\u4e5f\u6709\u5f88\u591a\u6587\u6863\u5728\u505a\u7b80\u7565\u63cf\u8ff0\u4e4b\u524d\u4f1a\u5199\u8fd9\u4e48\u4e00\u53e5 TBD: To Be Done(or Defined\/Discussed\/Decided\/Determined). \u6839\u636e\u8bed\u5883\u4e0d\u540c\u610f\u4e49\u6709\u6240\u533a\u522b\uff0c\u4f46\u4e00\u822c\u90fd\u662f\u8fd8\u6ca1\u641e\u5b9a\u7684\u610f\u601d  \u6700\u65b0\u8865\u5145  \u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/www.managertoday.com.tw\/english\/view\/52625\n  ASAP\uff08as soon as possible \u76e1\u5feb\uff09 BID\uff08break it down \u7d30\u5206\u660e\u7d30\uff09 BTW\uff08by the way \u9806\u5e36\u4e00\u63d0\uff09 COB\uff08close of business \u4e0b\u73ed\u6642\uff09 EOB\uff08end of business \u4e0b\u73ed\u6642\uff09 EOD\uff08end of day \u4eca\u5929\u4ee5\u5167\uff09 DOE\uff08depending on experience \u8996\u5de5\u4f5c\u7d93\u9a57\u800c\u5b9a\uff09 ETA\uff08estimated time of arrival \u9810\u8a08\u5230\u9054\u6642\u9593\uff09 FAQ\uff08frequently asked questions \u5e38\u554f\u7684\u554f\u984c\uff09 FTE\uff08full-time employee \u5168\u8077\u54e1\u5de5\uff09 FWIW\uff08for what it\u2019s worth \u7121\u8ad6\u5982\u4f55\u3001\u4e0d\u7ba1\u6709\u6c92\u6709\u7528\uff09 FYI\uff08for your information \u4f9b\u4f60\u53c3\u8003\uff08\u90f5\u4ef6\u5e38\u7528\uff09 FYR\uff08for your reference \u4f9b\u4f60\u53c3\u8003\uff09 FYU\uff08for your use \u4f9b\u4f60\u4f7f\u7528\uff09 IAM\uff08in a meeting \u6703\u8b70\u4e2d\uff09 IMO\uff08in my opinion \u500b\u4eba\u6dfa\u898b\u3001\u5728\u6211\u770b\u4f86\uff09 LET\uff08leaving early today \u4eca\u5929\u63d0\u65e9\u8d70\uff09 LMK\uff08let me know \u8b93\u6211\u77e5\u9053\u3001\u901a\u77e5\u6211\uff09 MoM\uff08month over month \u6708\u5ea6\u6bd4\u8f03\uff09 MTD\uff08month to date \u6708\u521d\u5230\u73fe\u5728\uff09 OOO\uff08out of office \u4e0d\u5728\u8fa6\u516c\u5ba4\uff09 OT\uff08over time \u52a0\u73ed\uff09 OTP\uff08on the phone \u901a\u8a71\u4e2d\uff09 PA\uff08performance appraisal \u7e3e\u6548\u8003\u6838\uff09 POC\uff08point of contact \u9996\u8981\u806f\u7e6b\u4eba\uff09 PTE\uff08part-time employee \u517c\u8077\u96c7\u54e1\uff09 PTO\uff08paid time off \u5e36\u85aa\u4f11\u5047\uff09 NDA\uff08Non-disclosure agreement \u4fdd\u5bc6\u5408\u7d04\uff09 NRN\uff08no reply necessary \u4e0d\u9700\u56de\u8986\uff09 NSFW\uff08not safe for work \u4e0d\u9069\u5408\u5de5\u4f5c\u5834\u57df\uff09 RFD\uff08request for discussion \u8acb\u6c42\u8a0e\u8ad6\uff09 RSVP\uff08R\u00e9pondez s\u2019il vous plait \u6cd5\u6587\u7684\u8acb\u56de\u8986\uff09 TBA\uff08to be announced \u5f85\u516c\u4f48\uff09 TBD\uff08to be determined \u5f85\u6c7a\u5b9a\uff09 TCC\uff08teleconference call \u96fb\u8a71\u6703\u8b70\uff09 TED\uff08Tell me, explain to me, describe to me\uff09 TL;DR\uff08Too long didn\u2019t read \u592a\u9577\uff0c\u6c92\u8b80\uff09 TOS\uff08terms of service \u670d\u52d9\u689d\u6b3e\uff09 TYT\uff08take your time \u5225\u8457\u6025\u3001\u6162\u6162\u4f86\uff09 WFH\uff08work from home \u5728\u5bb6\u8fa6\u516c\uff09 WIIFM\uff08what\u2019s in it for me \u9019\u5c0d\u6211\u6709\u4ec0\u9ebc\u597d\u8655\uff1f\uff09 WOM\uff08word of mouth \u53e3\u7891\u50b3\u64ad\uff09 YTD\uff08year to date \u5e74\u5e95\u3001\u4eca\u5e74\u4e4b\u5167\uff09 ","permalink":"https:\/\/wi1dcard.dev\/posts\/github-abbrs-collection\/","summary":"<p>\u641c\u96c6\u4e00\u4e9b GitHub \u5e38\u89c1\u9a9a\u7f29\u5199\uff0c\u4ee5\u5907\u67e5\u8be2\u4f7f\u7528\u3002<\/p>","title":"LGTM\uff08\uff1f\uff1f\uff1f\uff09\u8ff7\u4e4b\u9a9a\u7f29\u5199"},{"content":"hustcc\/lint-md \u662f\u4e00\u6b3e\u4e2d\u6587 Markdown \u5199\u4f5c\u89c4\u8303\u68c0\u67e5\u5de5\u5177\uff0c\u68c0\u67e5\u89c4\u5219\u6765\u6e90\u4e8e ruanyf\/document-style-guide\u3002\n\u914d\u5408 CI\/CD \u4f7f\u7528\uff0c\u5373\u80fd\u591f\u4ee5\u5b8c\u5168\u81ea\u52a8\u5316\u7684\u65b9\u5f0f\uff0c\u786e\u4fdd\u4f18\u79c0\u7684\u535a\u6587\u8d28\u91cf\uff0c\u957f\u671f\u4f7f\u7528\u8fd8\u53ef\u57f9\u517b\u826f\u597d\u7684\u5199\u4f5c\u4e60\u60ef\u3002\n\u51c6\u5907 \u9996\u5148\uff0c\u6211\u4eec\u9700\u8981\u719f\u6089\u8be5\u5de5\u5177\u3002\n# \u5168\u5c40\u5b89\u88c5 npm install -g lint-md # \u4f7f\u7528\u65b9\u6cd5\u5982\u4e0b lint-md &lt;files&gt; [--config &lt;config_file&gt;]  files \u4e3a\u4e00\u4e2a\u6216\u591a\u4e2a\u9700\u68c0\u67e5\u7684\u6587\u4ef6\u8def\u5f84\u3002 config_file \u4e3a JSON \u683c\u5f0f\u7684\u914d\u7f6e\u6587\u4ef6\u8def\u5f84\u3002  \u5176\u914d\u7f6e\u6587\u4ef6\u683c\u5f0f\u5982\u4e0b\u3002\n{ &#34;excludeFiles&#34;: [], \/\/ \u5ffd\u7565\u7684\u6587\u4ef6\u6216\u76ee\u5f55\u5217\u8868  &#34;rules&#34;: { &#34;no-empty-code&#34;: 1 \/\/ \u5b9a\u4e49\u89c4\u5219\u544a\u8b66\u7ea7\u522b  \/\/ ...  } } no-empty-code \u4e3a\u89c4\u5219\u540d\u79f0\uff0c\u5176\u503c\u4e0e\u544a\u8b66\u7ea7\u522b\u7684\u5bf9\u5e94\u5173\u7cfb\u5982\u4e0b\uff1a\n 0: Ignore \u5ffd\u7565\uff0c\u4e0d\u68c0\u67e5\u8be5\u89c4\u5219 1: Warning \u8b66\u544a\uff0c\u4f46\u8fdb\u7a0b\u9000\u51fa\u7801\u4e0d\u53d7\u5f71\u54cd\uff0c\u4f9d\u65e7\u4e3a\u96f6 2: Error \u9519\u8bef\uff0c\u9000\u51fa\u7801\u975e\u96f6\uff0c\u300c\u901a\u5e38\u300d\u4f1a\u4e2d\u65ad CI \u6d41\u7a0b\uff0c\u4e3a\u4f55\u300c\u901a\u5e38\u300d\u8be6\u89c1\u4e0b\u6587  \u8fc7\u7a0b \u5b98\u65b9\u6587\u6863\u63d0\u4f9b\u4e86\u4e00\u5957 Travis \u7684\u914d\u7f6e\u3002\nlanguage: node_js node_js: - &#34;10&#34; before_install: - npm i -g lint-md script: lint-md README.md \u5bf9\u4e8e\u6211\u7684\u535a\u5ba2\u5df2\u7ecf\u5927\u91cf\u4f7f\u7528 Node.js\uff0c\u4e14\u5305\u542b package.json\uff0c\u6211\u66f4\u503e\u5411\u4e8e\u4f7f\u7528\u4ee5\u4e0b\u7684\u914d\u7f6e\uff0c\u800c\u4e0d\u662f\u5168\u5c40\u5b89\u88c5\uff1a\nlanguage: node_js node_js: - &#34;10&#34; install: - npm install - export PATH=$PATH:$(pwd)\/node_modules\/.bin script: lint-md source\/_posts\/* --config lint-md.json # \u9002\u7528\u4e8e Hexo \u535a\u5ba2 \u53ef\u4ee5\u770b\u5230\uff0c\u6211\u4f7f\u7528 npm install \u547d\u4ee4\u5b89\u88c5\u6240\u6709 package.json \u4e2d\u58f0\u660e\u7684\u4f9d\u8d56\uff0c\u968f\u540e\u5c06 node_modules\/.bin \u76ee\u5f55\u8ffd\u52a0\u81f3 PATH \u73af\u5883\u53d8\u91cf\u3002\n\u8fd9\u6837\uff0c\u53ea\u9700\u6267\u884c\u4e00\u6b21 npm install\uff0c\u5728\u6dfb\u52a0\u540e\u7eed\u4f9d\u8d56\u65f6\u7edf\u4e00\u58f0\u660e\u5728 package.json \u5373\u53ef\uff0c\u4fdd\u6301\u914d\u7f6e\u6587\u4ef6\u7b80\u7565\u6613\u8bfb\u3002\n\u53e6\u5916\uff0c\u4fee\u6539 $PATH \u662f\u4e3a\u4e86\u8fbe\u5230\u4e0e\u5168\u5c40\u5b89\u88c5\u7edf\u4e00\u7684\u6548\u679c\u3002\u5373\u5728\u4f7f\u7528\u4f9d\u8d56\u7684\u53ef\u6267\u884c\u6587\u4ef6\u65f6\uff0c\u65e0\u9700 .\/node_modules\/.bin\/foo-bar \u800c\u53ea\u8981 foo-bar\u3002\nsource\/_posts\/* \u662f Hexo \u535a\u5ba2\u9ed8\u8ba4\u7684 Markdown \u6587\u7ae0\u6e90\u7801\u76ee\u5f55\uff0clint-md.json \u662f\u6211\u81ea\u5df1\u521b\u5efa\u7684\u914d\u7f6e\u6587\u4ef6\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a\n{ &#34;excludeFiles&#34;: [], &#34;rules&#34;: { &#34;no-empty-code-lang&#34;: 0, &#34;no-trailing-punctuation&#34;: 0 } } \u8be5\u914d\u7f6e\u6587\u4ef6\u53ef\u6839\u636e\u4f60\u7684\u9700\u8981\u81ea\u5b9a\u4e49\uff0c\u4ee5\u4e0a\u5ffd\u7565\u7684\u4e24\u4e2a\u89c4\u5219\u662f\u6211\u8ba4\u4e3a\u6ca1\u4ec0\u4e48\u5fc5\u8981\u7684\uff0c\u4ec5\u4f9b\u53c2\u8003\u3002\n\u53e6\u5916\u9700\u8981\u6ce8\u610f\u7684\u4e00\u70b9\u662f\uff0c\u6839\u636e Travis-CI \u4e2d\u5bf9\u4e8e Job Lifecycle \u7684\u6587\u6863\u63cf\u8ff0\uff1a\n If any of the commands in the first four phases of the job lifecycle return a non-zero exit code, the build is broken: If before_install, install or before_script returns a non-zero exit code, the build is errored and stops immediately. If script returns a non-zero exit code, the build is failed, but continues to run before being marked as failed.\n \u4e5f\u5c31\u662f\u8bf4\uff0c\u5982\u679c\u4f60\u7684 Travis \u914d\u7f6e\u6587\u4ef6\u50cf\u8fd9\u6837\uff0c\u5728 script \u5185\u6709\u591a\u6761\u547d\u4ee4\uff1a\nlanguage: node_js node_js: - &#34;10&#34; install: # ... script: - lint-md - hexo generate - hexo deploy # ... \u90a3\u4e48\u5982\u679c lint-md \u5931\u8d25\u540e\uff0c\u867d\u7136\u8fd4\u56de\u4e86\u975e\u96f6\u7684\u9000\u51fa\u7801\uff0c\u4f46 hexo generate \u4ee5\u53ca hexo deploy \u7b49\u540e\u7eed\u547d\u4ee4\u4f9d\u65e7\u4f1a\u6267\u884c\uff01\u53ea\u4e0d\u8fc7\u6d41\u7a0b\u7ed3\u675f\u540e\u4f1a\u6807\u8bb0\u8be5 Job \u4e3a\u5931\u8d25\uff08Failed\uff09\u72b6\u6001\u3002\n\u4e5f\u5c31\u662f\u8bf4\uff0c\u5982\u679c\u4f60\u7684 Markdown \u4e2d\u5b58\u5728\u4e0d\u89c4\u8303\u7684\u6587\u672c\uff0c\u88ab lint-md \u68c0\u51fa\u9519\u8bef\u540e\uff0c\u540e\u7eed\u7684\u751f\u6210\u548c\u90e8\u7f72\u6d41\u7a0b\u4f9d\u65e7\u4f1a\u7167\u5e38\u6267\u884c\uff01\u8fd9\u5c31\u8fbe\u4e0d\u5230\u300c\u5b58\u5728\u95ee\u9898\u5219\u4e0d\u53d1\u5e03\u300d\u7684\u6548\u679c\u4e86\u3002\u9488\u5bf9\u8fd9\u4e2a\u95ee\u9898\uff0c\u89e3\u51b3\u65b9\u6848\u6709\u4e8c\uff1a\n \u5728 script \u5185\u7684\u6240\u6709\u547d\u4ee4\u524d\uff0c\u6267\u884c set -e\uff0c\u8be6\u89c1 https:\/\/vaneyckt.io\/posts\/safer_bash_scripts_with_set_euxo_pipefail\/\u3002 \u6839\u636e\u4e0a\u6587\u5f15\u7528\u7684\u6587\u6863\u8bf4\u660e\uff0c\u5c06 lint-md \u547d\u4ee4\u79fb\u52a8\u5230 before_script \u5185\u3002  \u5176\u4e2d\uff0c\u79fb\u52a8\u5230 before_script \u4f1a\u9020\u6210\u4e00\u4e2a\u5fae\u5c0f\u7684\u5f71\u54cd \u2014\u2014 \u82e5\u547d\u4ee4\u6267\u884c\u8fd4\u56de\u975e\u96f6\u9000\u51fa\u7801\uff0c\u90a3\u4e48\u8be5 Job \u4f1a\u88ab\u7acb\u5373\u6807\u8bb0\u4e3a\u9519\u8bef\uff08Error\uff09\u72b6\u6001\u5e76\u505c\u6b62\u6267\u884c\uff0c\u800c\u975e\u5931\u8d25\uff08Failed\uff09\u72b6\u6001\u3002\u8bf7\u6ce8\u610f Travis-CI \u4e2d\u8fd9\u70b9\u5c0f\u533a\u522b\u3002\n\u95ee\u9898 \u76ee\u524d\u8be5\u9879\u76ee\u8fd8\u4e0d\u591f\u5b8c\u5584\uff0c\u53c2\u89c1\uff1a\nIssue #33, #34\u3002\n\u62d3\u5c55 \u5f53\u7136\uff0c\u8be5\u5de5\u5177\u4e5f\u53ef\u4ee5\u672c\u5730\u4f7f\u7528\uff0c\u8fd8\u5177\u5907 --fix \u9009\u9879\uff0c\u80fd\u591f\u81ea\u52a8\u4fee\u590d\u4e0d\u7b26\u5408\u89c4\u8303\u7684\u6587\u672c\u3002\n\u53e6\u5916\uff0cdkhamsing\/awesome_bot \u662f\u4e00\u6b3e\u9a8c\u8bc1\u6587\u4ef6\u5185 URL \u662f\u5426\u6709\u6548\u7684\u5de5\u5177\u3002\u539f\u672c\u7528\u4e8e\u5404\u7c7b awesome \u9879\u76ee\u68c0\u67e5\u5176\u94fe\u63a5\u3001\u4ee5\u53ca\u6536\u5230 PR \u65f6\uff0c\u81ea\u52a8\u68c0\u67e5\u5305\u542b\u7684 URLs \u662f\u5426\u53ef\u8bbf\u95ee\u3002\u540c\u6837\uff0c\u4e5f\u53ef\u4ee5\u7ed9 Markdown \u535a\u5ba2\u4f7f\u7528\uff0c\u80fd\u591f\u786e\u4fdd\u535a\u6587\u5185\u7684\u94fe\u63a5\u53ef\u7528\u3002\n\u867d\u7136\uff0c\u6211\u5728\u672c\u5730\u4f7f\u7528\u8be5\u5de5\u5177\u5bf9\u6240\u6709\u6587\u7ae0\u7684\u94fe\u63a5\u53ef\u7528\u6027\u8fdb\u884c\u4e86\u4e00\u904d\u300c\u666e\u67e5\u300d\uff0c\u4f46\u6211\u51b3\u5b9a\u4e0d\u5728 CI \u6d41\u7a0b\u5185\u52a0\u5165\u8be5\u5de5\u5177\u3002\u4e3b\u8981\u7531\u4e8e\u914d\u7f6e\u9879\u4e0d\u591f\u4e30\u5bcc\uff0c\u90e8\u5206\u94fe\u63a5\u6211\u300c\u786e\u5b9e\u300d\u5e0c\u671b\u5b83\u5931\u6548\uff0c\u4f46\u65e0\u6cd5\u5ffd\u7565\u67d0\u6587\u4ef6\u4e2d\u67d0\u4e00\u7279\u5b9a\u94fe\u63a5\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/lint-your-posts-with-ci\/","summary":"<p><a href=\"https:\/\/github.com\/hustcc\/lint-md\" target=\"_blank\">hustcc\/lint-md<\/a> \u662f\u4e00\u6b3e\u4e2d\u6587 Markdown \u5199\u4f5c\u89c4\u8303\u68c0\u67e5\u5de5\u5177\uff0c\u68c0\u67e5\u89c4\u5219\u6765\u6e90\u4e8e <a href=\"https:\/\/github.com\/ruanyf\/document-style-guide\" target=\"_blank\">ruanyf\/document-style-guide<\/a>\u3002<\/p>\n<p>\u914d\u5408 CI\/CD \u4f7f\u7528\uff0c\u5373\u80fd\u591f\u4ee5\u5b8c\u5168\u81ea\u52a8\u5316\u7684\u65b9\u5f0f\uff0c\u786e\u4fdd\u4f18\u79c0\u7684\u535a\u6587\u8d28\u91cf\uff0c\u957f\u671f\u4f7f\u7528\u8fd8\u53ef\u57f9\u517b\u826f\u597d\u7684\u5199\u4f5c\u4e60\u60ef\u3002<\/p>","title":"\u81ea\u52a8\u5316 Markdown \u535a\u6587\u5199\u4f5c\u89c4\u8303\u68c0\u67e5"},{"content":"afc163\/fanyi \u662f\u4e00\u6b3e\u547d\u4ee4\u884c\u67e5\u8bcd\u5de5\u5177\u3002\u5b9e\u7528\u3001\u7f8e\u89c2\uff0c\u662f\u6211\u5bf9\u5b83\u7684\u7b2c\u4e00\u5370\u8c61\u3002\n\u8be5\u5de5\u5177\u5b9e\u7528 Node.js \u7f16\u5199\uff0c\u56e0\u6b64\u9700\u8981\u4f7f\u7528 npm \u5b89\u88c5\u3002\nnpm install fanyi -g \u4f7f\u7528\u65b9\u6cd5\u7b80\u5355\u5230\u4e0d\u80fd\u518d\u7b80\u5355\u3002\nfanyi spark # \u6216 fy spark \u793a\u4f8b\u8f93\u51fa\u5982\u4e0b\u3002\n\u5728\u6211\u7684 macOS \u4e0a\uff0c\u67e5\u8bcd\u7684\u540c\u65f6\u4f1a\u5c06\u8be5\u8bcd\u53d1\u97f3\u300c\u8bfb\u300d\u51fa\u6765\uff0c\u662f\u7684\uff0c\u901a\u8fc7\u58f0\u5361\u64ad\u653e\u3002\n\u636e\u9879\u76ee\u6587\u6863\u63cf\u8ff0\uff0c\u67e5\u8bcd\u7684\u6570\u636e\u6765\u6e90\u662f &lt;iciba.com&gt;\u3001&lt;fanyi.youdao.com&gt; \u4ee5\u53ca &lt;dictionaryapi.com&gt;\uff0c\u4e14\u6682\u65f6\u53ea\u652f\u6301\u4e2d\u82f1\u4e92\u8bd1\u3002\n$ fanyi &#34;for your information&#34; $ fanyi \u548c\u8c10 $ fanyi \u5b50\u975e\u9c7c\u7109\u77e5\u9c7c\u4e4b\u4e50 \u6700\u540e\uff0c\u7ecf\u8fc7\u5c1d\u8bd5\uff0c\u8fd8\u662f\u5efa\u8bae\u53ea\u7528\u4e8e \u82f1\u8bd1\u4e2d\uff0c\u5e76\u4e14\u5c3d\u53ef\u80fd\u53ea\u67e5 \u5355\u8bcd \u6216 \u5e38\u89c1\u642d\u914d\u8bcd\u7ec4\uff0c\u957f\u53e5\u5b50\u662f\u65e0\u6cd5\u50cf Google Translate \u90a3\u6837\u67e5\u51fa\u7ed3\u679c\u7684\u3002\u6bd5\u7adf\u6570\u636e\u6765\u6e90\u662f\u300c\u8bcd\u5178\u300d\uff0c\u800c\u975e\u300c\u7ffb\u8bd1\u300d\u3002\u53e6\u5916\uff0c\u8bfb\u97f3\u7684\u51c6\u786e\u6027\u3001\u5730\u57df\u6027\u4e5f\u6709\u5f85\u8003\u91cf\uff0c\u6709\u80fd\u529b\u9605\u8bfb\u97f3\u6807\u7684\u8bdd\uff0c\u8fd8\u662f\u5efa\u8bae\u4f7f\u7528 https:\/\/dictionary.cambridge.org\/ \u7b49\u4e13\u4e1a\u8bcd\u5178\u6bd4\u8f83\u5408\u9002\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/translate-words-via-command-line\/","summary":"<p><a href=\"https:\/\/github.com\/afc163\/fanyi\" target=\"_blank\">afc163\/fanyi<\/a> \u662f\u4e00\u6b3e\u547d\u4ee4\u884c\u67e5\u8bcd\u5de5\u5177\u3002\u5b9e\u7528\u3001\u7f8e\u89c2\uff0c\u662f\u6211\u5bf9\u5b83\u7684\u7b2c\u4e00\u5370\u8c61\u3002<\/p>","title":"\u7a0b\u5e8f\u5458\u547d\u4ee4\u884c\u67e5\u8bcd\u597d\u5e2e\u624b"},{"content":"\u8fd1\u671f\u5728\u7814\u7a76\u7cfb\u7edf\u76d1\u63a7\u9884\u8b66\uff0c\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1aCPU \u4f7f\u7528\u7387\u9884\u8b66\u3001\u5185\u5b58\u4f7f\u7528\u7387\u9884\u8b66\u3001\u78c1\u76d8\u4f7f\u7528\u7387\u9884\u8b66\u4ee5\u53ca IO \u9884\u8b66\u3002\n\u5728\u6d4b\u8bd5\u8fc7\u7a0b\u4e2d\uff0c\u9700\u8981\u6a21\u62df\u7cfb\u7edf\u8d1f\u8f7d\u6765\u9a8c\u8bc1\u9884\u8b66\u89c4\u5219\u662f\u5426\u6709\u6548\u3002\u6545\u603b\u7ed3\u51e0\u79cd\u6a21\u62df\u8d1f\u8f7d\u7684\u65b9\u5f0f\uff0c\u4ee5\u4f9b\u65e5\u540e\u67e5\u8be2\u3002\nCPU \u4f7f\u7528\u7387 \u65b9\u6cd5\u5f88\u591a\uff0c\u6700\u7b80\u5355\u76f4\u63a5\u7684\u6709\uff1a\n cat \/dev\/zero &gt; \/dev\/null cat \/dev\/urandom | gzip -9 &gt; \/dev\/null dd if=\/dev\/zero of=\/dev\/null yes &gt; \/dev\/null &hellip;  \u4ee5\u4e0a\u65b9\u6cd5\u4ec5\u80fd\u5bf9\u5355\u6838\u65bd\u52a0\u538b\u529b\uff0c\u591a\u6838\u5fc3\u53ef\u4ee5\u4f7f\u7528 for \u5faa\u73af + \u547d\u4ee4\u7ed3\u5c3e &amp;\uff0c\u6216\u4f7f\u7528\u591a\u4e2a\u7ba1\u9053\u8fde\u63a5\u6765\u5b9e\u73b0\uff1a\n for i in 'seq 1 $(cat \/proc\/cpuinfo | grep &quot;physical id&quot; | wc -l)'; do cat \/dev\/zero &gt; \/dev\/null &amp; done cat \/dev\/urandom | gzip -9 | gzip -d | gzip -9 | gzip -d &gt; \/dev\/null  \u78c1\u76d8\u4f7f\u7528\u7387 \u4e0a\u8282\u6211\u4eec\u4f7f\u7528\u5230\u4e86 dd \u547d\u4ee4\uff0c\u8be5\u547d\u4ee4\u7ed3\u5408 \/dev\/zero \u4e5f\u53ef\u4ee5\u88ab\u7528\u4e8e\u8f93\u51fa\u4e00\u5b9a\u5927\u5c0f\u7684\u6587\u4ef6\uff0c\u4ece\u800c\u6a21\u62df\u78c1\u76d8\u4f7f\u7528\u7387\u3002\n\u4f8b\u5982\uff1a\ndd if=\/dev\/zero of=loadfile bs=1M count=1024 # \u8f93\u51fa 1024M \u7684 \\0 \u5230 loadfile \u78c1\u76d8 IO \u5229\u7528\u521a\u521a\u751f\u6210\u7684 loadfile\uff0c\u52a0\u4e0a cp \u547d\u4ee4\u53ef\u4ee5\u4e00\u5b9a\u7a0b\u5ea6\u5730\u6a21\u62df\u987a\u5e8f IO\uff1a\nwhile true; do cp loadfile loadfile1; done # \u65e0\u9650\u5faa\u73af\u590d\u5236\u6587\u4ef6 \u5185\u5b58\u4f7f\u7528\u7387 \u56de\u770b\u524d\u9762\u7684\u51e0\u9879\u9700\u6c42\uff0c\u5176\u5b9e\u90fd\u53ef\u4ee5\u901a\u8fc7 stress \u5de5\u5177\u548c &lt;code&gt;lookbusy&lt;\/code&gt; \u5de5\u5177\u5b9e\u73b0\uff0c\u5e76\u4e14\u66f4\u52a0\u7cbe\u51c6\u3001\u53ef\u63a7\u3001\u6613\u7528\u3002\n\u4ee5\u4e0b\u5206\u522b\u5217\u51fa\u51e0\u4e2a\u4f8b\u5b50\uff0c\u65b9\u4fbf\u7167\u6284\u7406\u89e3\u3002\nstress --cpu 2 # \u4ea7\u751f 2 \u4e2a\u5de5\u4f5c\u8fdb\u7a0b\u5bf9 CPU \u65bd\u52a0\u538b\u529b\uff0c\u4e5f\u5c31\u662f\u5c06\u4f1a\u5360\u7528\u4e24\u4e2a CPU \u6838\u5fc3 stress --vm 1 --vm-bytes 128M --vm-hang 0 # \u4ea7\u751f 1 \u4e2a\u5de5\u4f5c\u8fdb\u7a0b\uff0c\u5360\u7528 128MB \u5185\u5b58\u5e76\u4fdd\u6301 stress --io 1 # \u4ea7\u751f 1 \u4e2a\u5de5\u4f5c\u8fdb\u7a0b\u5bf9 IO \u65bd\u52a0\u538b\u529b lookbusy -c 50 # \u5360\u7528\u6240\u6709 CPU \u6838\u5fc3\u5404 50% lookbusy -c 50 -n 2 # \u5360\u7528\u4e24\u4e2a CPU \u6838\u5fc3\u5404 50% lookbusy -c 50-80 -r curve # \u5360\u7528\u6240\u6709 CPU \u6838\u5fc3\u5728 50%-80% \u5de6\u53f3\u6d6e\u52a8 lookbusy -c 0 -m 128MB -M 1000 # \u6bcf 1000 \u6beb\u79d2\uff0c\u5faa\u73af\u91ca\u653e\u5e76\u5206\u914d 128MB \u5185\u5b58 lookbusy -c 0 -d 1GB -b 1MB -D 10 # \u6bcf 10 \u6beb\u79d2\uff0c\u5faa\u73af\u8fdb\u884c 1MB \u78c1\u76d8\u5199\u5165\uff0c\u4e34\u65f6\u6587\u4ef6\u4e0d\u8d85\u8fc7 1GB \u4ee5\u4e0a\u547d\u4ee4\u7684\u53c2\u6570\u5747\u53ef\u7ed3\u5408\u4f7f\u7528\uff0c\u540c\u65f6\u5bf9\u7cfb\u7edf\u591a\u4e2a\u7ef4\u5ea6\u65bd\u52a0\u538b\u529b\u3002\n\u5176\u5b83\u5de5\u5177  stress-ng: https:\/\/kernel.ubuntu.com\/~cking\/stress-ng\/ cpulimit: https:\/\/github.com\/opsengine\/cpulimit cpu-load-generator: https:\/\/github.com\/beloglazov\/cpu-load-generator fio: https:\/\/github.com\/axboe\/fio  \u53c2\u8003  https:\/\/stackoverflow.com\/questions\/2925606\/how-to-create-a-cpu-spike-with-a-bash-command https:\/\/nitinbhojwani-tech-talk.blogspot.com\/2017\/05\/simulate-cpu-memory-and-disk-load-on.html https:\/\/bash-prompt.net\/guides\/create-system-load\/ https:\/\/stackoverflow.com\/questions\/1971422\/linux-how-to-put-a-load-on-system-memory https:\/\/www.cyberciti.biz\/faq\/stress-test-linux-unix-server-with-stress-ng\/ https:\/\/unix.stackexchange.com\/questions\/99334\/how-to-fill-90-of-the-free-memory  \u62d3\u5c55 \u8ba1\u7b97 IO \u5360\u7528\u7387\uff08\u767e\u5206\u6bd4\uff09\u7684\u65b9\u6cd5\uff1ahttps:\/\/unix.stackexchange.com\/questions\/318274\/how-to-calculate-disk-io-load-percentage\n","permalink":"https:\/\/wi1dcard.dev\/posts\/simulate-system-load-in-linux\/","summary":"<p>\u8fd1\u671f\u5728\u7814\u7a76\u7cfb\u7edf\u76d1\u63a7\u9884\u8b66\uff0c\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1aCPU \u4f7f\u7528\u7387\u9884\u8b66\u3001\u5185\u5b58\u4f7f\u7528\u7387\u9884\u8b66\u3001\u78c1\u76d8\u4f7f\u7528\u7387\u9884\u8b66\u4ee5\u53ca IO \u9884\u8b66\u3002<\/p>\n<p>\u5728\u6d4b\u8bd5\u8fc7\u7a0b\u4e2d\uff0c\u9700\u8981\u6a21\u62df\u7cfb\u7edf\u8d1f\u8f7d\u6765\u9a8c\u8bc1\u9884\u8b66\u89c4\u5219\u662f\u5426\u6709\u6548\u3002\u6545\u603b\u7ed3\u51e0\u79cd\u6a21\u62df\u8d1f\u8f7d\u7684\u65b9\u5f0f\uff0c\u4ee5\u4f9b\u65e5\u540e\u67e5\u8be2\u3002<\/p>","title":"Linux \u4e2d\u6a21\u62df\u591a\u79cd\u7cfb\u7edf\u8d1f\u8f7d\u7684\u65b9\u6cd5"},{"content":"\u5927\u6982\u60f3\u6cd5\uff1a\u8f6c\u6362\u6211\u7684\u7b80\u5386 HTML \u5230 PDF -&gt; \u5c06 PDF \u90e8\u7f72\u5230\u4e03\u725b\u4e91 -&gt; \u8bbf\u5ba2\u53ef\u76f4\u63a5\u4e0b\u8f7d\u6700\u65b0\u7248\u672c PDF \u4e14\u4e0e\u5728\u7ebf\u7b80\u5386\u540c\u6b65\u3002\n\u4ee5\u4e0a\u8fc7\u7a0b\u5747\u57fa\u4e8e Travis CI \u5b9e\u73b0\uff0c\u66ff\u6362\u6210\u5176\u5b83\u4ea6\u53ef\u3002\u5e73\u65f6\u6211\u4eec\u63d0\u5230\u7684 CI\/CD\uff0c\u800c\u672c\u4f8b\u5373\u4e3a\u7b80\u6613\u7684 CD\uff08Continuous Delivery\uff09\u5b9e\u4f8b\u3002\n\u7f16\u5199 Travis \u914d\u7f6e\u6587\u4ef6 services: - docker before_script: - docker pull arachnysdocker\/athenapdf - curl -v -o qshell.zip http:\/\/devtools.qiniu.com\/qshell-v2.3.5.zip - ls -l qshell.zip - unzip qshell.zip - mv qshell_linux_x64 qshell script: - docker run --rm -v $(pwd):\/converted\/ arachnysdocker\/athenapdf athenapdf --margins=none https:\/\/wi1dcard.github.io\/resume\/ resume.pdf - .\/qshell account $QINIU_AK $QINIU_SK [\u4efb\u9009\u540d\u79f0] - .\/qshell fput [\u4e03\u725b Bucket \u540d\u79f0] get-resume resume.pdf -w \u4ee5\u4e0a\uff0c\u6211\u4f7f\u7528\u4e86\u4e24\u4e2a\u5173\u952e\u7684\u5de5\u5177\u3002\n athenapdf\uff1a\u4e00\u6b3e\u5b98\u65b9\u63d0\u4f9b Docker \u955c\u50cf\u3001\u7b80\u5355\u6613\u7528\u7684 PDF \u8f6c\u6362\u89e3\u51b3\u65b9\u6848\uff0c\u53ef\u7528\u4e8e\u66ff\u4ee3 wkhtmltopdf\u3002 qshell\uff1a\u5229\u7528\u4e03\u725b\u6587\u6863\u4e0a\u516c\u5f00\u7684 API \u5b9e\u73b0\u7684\u4e00\u4e2a\u65b9\u4fbf\u5f00\u53d1\u8005\u6d4b\u8bd5\u548c\u4f7f\u7528\u4e03\u725b API \u670d\u52a1\u7684\u547d\u4ee4\u884c\u5de5\u5177\u3002  \u5728 before_script \u4e2d\u6211\u62c9\u53d6\u4e86 athenapdf \u7684\u5b98\u65b9 Docker \u955c\u50cf\uff0c\u63a5\u7740\u4e0b\u8f7d\u4e86 qshell \u7684\u53d1\u884c\u5305\u3001\u89e3\u538b\u5e76\u91cd\u547d\u540d\u3002\n\u5728 script \u4e2d\uff0c\u6211\u9996\u5148\u6267\u884c athenapdf \u8f6c\u6362\u6211\u7684\u5728\u7ebf\u7b80\u5386 https:\/\/wi1dcard.github.io\/resume\/ \u4e3a resume.pdf\u3002\u968f\u540e\u914d\u7f6e qshell \u6240\u9700\u7684\u4e03\u725b\u4e91 AK\u3001SK\uff0c\u8be5\u5bc6\u94a5\u5bf9\u4f60\u53ef\u4ee5\u5728\u4e03\u725b\u4e91\u7684\u7ba1\u7406\u9875\u9762\u751f\u6210\u3002\n\u6ce8\u610f\u8fd9\u91cc\u6211\u4f7f\u7528\u4e86 $QINIU_AK \u548c $QINIU_SK \u73af\u5883\u53d8\u91cf\uff0c\u8fd9\u4e24\u4e2a\u73af\u5883\u53d8\u91cf\u662f\u5728 Travis \u7684\u9879\u76ee\u8bbe\u7f6e\u5185\u914d\u7f6e\u597d\u7684\uff0c\u5b83\u4eec\u4e0d\u4f1a\u88ab\u663e\u793a\u5728 CI \u65e5\u5fd7\u4e2d\uff0c\u56e0\u6b64\u53ef\u4ee5\u8fbe\u5230\u4e00\u5b9a\u7684\u4fdd\u5bc6\u6548\u679c\u3002\u70b9\u51fb\u8fd9\u91cc \u53ef\u67e5\u770b\u5b98\u65b9\u6587\u6863\u3002\n\u6700\u540e\uff0c\u4f7f\u7528 qshell fput \u5c06\u6587\u4ef6\u4e0a\u4f20\u81f3\u5bf9\u8c61\u5b58\u50a8\u3002\u5176\u4e2d\uff0cget-resume \u662f\u8be5\u6587\u4ef6\uff08\u6216\u8005\u8bf4\uff0cObject\uff09\u7684 Key\uff0c\u53ef\u4ee5\u7406\u89e3\u4e3a URI\u3002\u800c resume.pdf \u5219\u662f\u672c\u5730\u751f\u6210\u7684\u7b80\u5386 PDF \u6587\u4ef6\u8def\u5f84\u3002\n\u53e6\u5916\uff0cathenapdf \u7684\u529f\u80fd\u8fdc\u4e0d\u6b62\u7b80\u6613\u7684 CLI \u5de5\u5177\uff0c\u5b9e\u9645\u4e0a\u5b83\u8fd8\u63d0\u4f9b\u4e86\u57fa\u4e8e Go \u7684\u5fae\u670d\u52a1\uff0c\u4e5f\u5c31\u662f\u8bf4\u53ef\u4ee5\u72ec\u7acb\u8fd0\u884c\u4e3a\u4e00\u53f0\u300cPDF \u8f6c\u6362\u300d\u670d\u52a1\u3002\u6709\u5174\u8da3\u53ef\u67e5\u770b\u9879\u76ee\u9875\u9762\u7684\u4ecb\u7ecd\u3002\n\u6539\u9020 Hexo \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cHexo \u5728\u751f\u6210\u7ad9\u70b9\u65f6\uff0c\u4f1a\u62f7\u8d1d source \u76ee\u5f55\u4e0b\u7684\u666e\u901a\u6587\u4ef6\u5230 public\uff0c\u4f46\u4f3c\u4e4e .travis.yml \u4e0d\u77e5\u4e3a\u4f55\uff08\u53ef\u80fd\u662f Yaml \u4e5f\u4f1a\u88ab\u6e32\u67d3\u5427\uff09\uff0c\u6267\u884c hexo generate \u4e0d\u4f1a\u590d\u5236\u8be5\u6587\u4ef6\u3002\n\u56e0\u4e3a\u5bf9 Hexo \u7684\u597d\u611f\u5ea6\u672c\u6765\u4e5f\u4e0d\u9ad8\uff0c\u524d\u6bb5\u65f6\u95f4\u8fd8\u5dee\u70b9\u6362\u6389\u5b83\uff08\u7136\u800c\u5176\u5b83\u9759\u6001\u535a\u5ba2\u6ca1\u4ec0\u4e48\u770b\u7740\u987a\u773c\u7684\u4e3b\u9898\uff09\uff0c\u6240\u4ee5\u6211\u6ca1\u6709\u5bf9 Hexo \u7684\u8fd0\u884c\u8fc7\u7a0b\u8fdb\u884c\u6df1\u7a76\uff0c\u7528\u4e86\u4e00\u4e2a\u6bd4\u8f83\u7cd9\u7684\u89e3\u51b3\u65b9\u6848\u3002\n\u6839\u636e Hexo \u6587\u6863\uff0c\u5176\u4f1a\u6267\u884c scripts \u76ee\u5f55\u5185\u7684\u6240\u6709\u811a\u672c\uff0c\u53ef\u7528\u4e8e\u6302\u8f7d\u4e8b\u4ef6\u6765\u5b9e\u73b0\u4e00\u4e9b\u81ea\u5b9a\u4e49\u529f\u80fd\u3002\n If your plugin is relatively simple, it\u2019s recommended to use a script. All you need to do is put your JavaScript files in the scripts folder and Hexo will load them during initialization.\n \u4e8e\u662f\uff0c\u521b\u5efa scripts\/cp-travis-configuration.js\uff1a\nconst fs = require(&#39;hexo-fs&#39;); const log = require(&#39;hexo-log&#39;)({ debug: false, silent: false }); hexo.on(&#39;generateAfter&#39;, function () { fs.copyFile(&#39;source\/.travis.yml&#39;, &#39;public\/.travis.yml&#39;, function (err) { if (err) { throw err; } else { log.info(&#39;Travis CI configuration copied.&#39;); } }); }); \u975e\u5e38\u7b80\u5355\u7c97\u66b4\u5730\u5c06\u6587\u4ef6\u62f7\u8d1d\u8fc7\u53bb\u3002\n\u7ed3\u679c \u5173\u4e8e Travis CI \u7684\u57fa\u7840\u4f7f\u7528\u4e0d\u518d\u8d58\u8ff0\u3002\n\u4ee5\u4e0a\uff0cGit \u63d0\u4ea4\u540e\u89e6\u53d1 CI \u6267\u884c\uff0c\u5373\u53ef\u901a\u8fc7\u4e03\u725b\u4e91\u878d\u5408 CDN \u5185\u914d\u7f6e\u7684\u57df\u540d + get-resume \u6765\u8bbf\u95ee\u5230\u6211\u7684\u7b80\u5386\u5566\u3002\n\u4f8b\u5982\uff1ahttp:\/\/your-domain\/get-resume\u3002\n\u5f03\u5751 \u539f\u56e0\u6709\u4e8c\uff1a\n \u5783\u573e\u4e03\u725b\u8c8c\u4f3c\u6ca1\u6709\u5bf9\u56fd\u5916\u8bbf\u95ee\u505a\u826f\u597d\u7684\u4f18\u5316\u652f\u6301\uff0c\u4ee5\u81f3\u4e8e CI \u673a\u5668\u4f7f\u7528 CURL \u4e0b\u8f7d\u65f6\u6781\u5176\u4e0d\u7a33\u5b9a\uff0c\u52a8\u4e0d\u52a8\u5c31\u65e0\u6cd5\u62ff\u5230 qshell\uff0c\u800c\u5728 GitHub Releases \u5185\u53c8\u6ca1\u6709\u7f16\u8bd1\u597d\u7684\u53ef\u6267\u884c\u6587\u4ef6\u3002\u6211\u5df2\u7ecf\u63d0\u4ea4 Issue \u4f46\u4e0d\u786e\u5b9a\u4f55\u65f6\u624d\u4f1a\u5f97\u5230\u7b54\u590d\u3002\u5509\uff0c\u56fd\u5185\u4f01\u4e1a\u7684\u901a\u75c5\u3002 \u4f7f\u7528\u56fd\u5185 CDN \u57df\u540d\u8981\u5907\u6848\u3002\u8fd8\u597d\u6211\u6709\u4e00\u4e2a\u591a\u5e74\u524d\u901a\u8fc7\u4e2a\u4eba\u5907\u6848\u7684\u57df\u540d\uff0c\u6682\u65f6\u80fd\u591f\u6491\u4e00\u4e0b\uff0c\u4f46\u4e0d\u662f\u957f\u4e45\u4e4b\u8ba1\u3002  \u76ee\u524d\uff0c\u6211\u5df2\u7ecf\u91cd\u65b0\u914d\u7f6e CI\uff0c\u56de\u5934\u518d\u53e6\u5199\u535a\u6587\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/convert-html-to-pdf-with-ci\/","summary":"<p>\u5927\u6982\u60f3\u6cd5\uff1a<code>\u8f6c\u6362\u6211\u7684\u7b80\u5386 HTML \u5230 PDF<\/code> -&gt; <code>\u5c06 PDF \u90e8\u7f72\u5230\u4e03\u725b\u4e91<\/code> -&gt; <code>\u8bbf\u5ba2\u53ef\u76f4\u63a5\u4e0b\u8f7d\u6700\u65b0\u7248\u672c PDF \u4e14\u4e0e\u5728\u7ebf\u7b80\u5386\u540c\u6b65<\/code>\u3002<\/p>\n<p>\u4ee5\u4e0a\u8fc7\u7a0b\u5747\u57fa\u4e8e Travis CI \u5b9e\u73b0\uff0c\u66ff\u6362\u6210\u5176\u5b83\u4ea6\u53ef\u3002\u5e73\u65f6\u6211\u4eec\u63d0\u5230\u7684 CI\/CD\uff0c\u800c\u672c\u4f8b\u5373\u4e3a\u7b80\u6613\u7684 CD\uff08<code>Continuous Delivery<\/code>\uff09\u5b9e\u4f8b\u3002<\/p>","title":"\u6301\u7eed\u751f\u6210\u7b80\u5386 PDF \u5e76\u90e8\u7f72\u81f3\u4e03\u725b\u4e91"},{"content":"JSON Web Tokens\uff0c\u53c8\u79f0 JWT\u3002\u672c\u6587\u4f5c\u8005\u5c06\u8be6\u89e3\uff1a\u4e3a\u4f55 JWT \u4e0d\u9002\u5408\u5b58\u50a8 Session\uff0c\u4ee5\u53ca JWT \u5f15\u53d1\u7684\u5b89\u5168\u9690\u60a3\u3002\u671b\u5404\u4f4d\u4f7f\u7528\u524d\u4e09\u601d\u3002\n \u539f\u6587\u5730\u5740\uff1ahttp:\/\/cryto.net\/~joepie91\/blog\/2016\/06\/13\/stop-using-jwt-for-sessions\/\n \u5341\u5206\u4e0d\u5e78\uff0c\u6211\u53d1\u73b0\u8d8a\u6765\u8d8a\u591a\u7684\u4eba\u5f00\u59cb\u63a8\u8350\u4f7f\u7528 JWT \u7ba1\u7406\u7f51\u7ad9\u7684\u7528\u6237\u4f1a\u8bdd\uff08Session\uff09\u3002\u5728\u672c\u6587\u4e2d\uff0c\u6211\u5c06\u8bf4\u660e\u4e3a\u4f55\u8fd9\u662f\u4e2a\u975e\u5e38\u975e\u5e38\u5dee\u52b2\u7684\u60f3\u6cd5\u3002\n\u4e3a\u4e86\u907f\u514d\u7591\u60d1\u548c\u6b67\u4e49\uff0c\u9996\u5148\u5b9a\u4e49\u4e00\u4e9b\u672f\u8bed\uff1a\n \u65e0\u72b6\u6001 JWT\uff08Stateless JWT\uff09\uff1a\u5305\u542b Session \u6570\u636e\u7684 JWT Token\u3002Session \u6570\u636e\u5c06\u88ab\u76f4\u63a5\u7f16\u7801\u8fdb Token \u5185\u3002 \u6709\u72b6\u6001 JWT\uff08Stateful JWT\uff09\uff1a\u5305\u542b Session \u5f15\u7528\u6216\u5176 ID \u7684 JWT Token\u3002Session \u6570\u636e\u5b58\u50a8\u5728\u670d\u52a1\u7aef\u3002 Session token\uff08\u53c8\u79f0 Session cookie\uff09\uff1a\u6807\u51c6\u7684\u3001\u53ef\u88ab\u7b7e\u540d\u7684 Session ID\uff0c\u4f8b\u5982\u5404\u7c7b Web \u6846\u67b6\uff08\u8bd1\u8005\u6ce8\uff1a\u5305\u62ec Laravel\uff09\u5185\u5df2\u7ecf\u4f7f\u7528\u4e86\u5f88\u4e45\u7684 Session \u673a\u5236\u3002Session \u6570\u636e\u540c\u6837\u5b58\u50a8\u5728\u670d\u52a1\u7aef\u3002  \u9700\u8981\u6f84\u6e05\u7684\u662f\uff1a\u672c\u6587\u5e76\u975e\u6311\u8d77\u300c\u6c38\u8fdc\u4e0d\u8981\u4f7f\u7528 JWT\u300d\u7684\u4e89\u8bba \u2014\u2014 \u53ea\u662f\u60f3\u8bf4\u660e JWT \u5e76\u4e0d\u9002\u5408\u4f5c\u4e3a Session \u673a\u5236\uff0c\u4e14\u5341\u5206\u5371\u9669\u3002JWT \u5728\u5176\u5b83\u65b9\u9762\u7684\u786e\u6709\u5176\u7528\u6b66\u4e4b\u5730\u3002\u672c\u6587\u7ed3\u5c3e\uff0c\u6211\u5c06\u7b80\u77ed\u5730\u4ecb\u7ecd\u4e00\u4e9b\u5408\u7406\u7528\u9014\u3002\n\u9996\u5148\u9700\u8981\u8bf4\u660e \u5f88\u591a\u4eba\u9519\u8bef\u5730\u5c1d\u8bd5\u6bd4\u8f83 Cookies \u548c JWT\u3002\u8fd9\u79cd\u5bf9\u6bd4\u6beb\u65e0\u610f\u4e49\uff0c\u5c31\u50cf\u5bf9\u6bd4\u5185\u5b58\u548c\u786c\u76d8\u4e00\u6837\u3002Cookies \u662f\u4e00\u79cd\u5b58\u50a8\u673a\u5236\uff0c\u7136\u800c JWT Tokens \u662f\u88ab\u52a0\u5bc6\u5e76\u7b7e\u540d\u540e\u7684\u4ee4\u724c\u3002\n\u5b83\u4eec\u5e76\u4e0d\u5bf9\u7acb \u2014\u2014 \u76f8\u53cd\uff0c\u4ed6\u4eec\u53ef\u4ee5\u72ec\u7acb\u6216\u7ed3\u5408\u4f7f\u7528\u3002\u6b63\u786e\u7684\u5bf9\u6bd4\u5e94\u5f53\u662f\uff1aSession \u5bf9\u6bd4 JWT\uff0c\u4ee5\u53ca Cookies \u5bf9\u6bd4 Local Storage\u3002\n\u5728\u672c\u6587\u4e2d\uff0c\u6211\u5c06\u628a JWT Tokens \u540c Session \u5c55\u5f00\u5bf9\u6bd4\uff0c\u5e76\u5076\u5c14\u5bf9\u6bd4 Cookie \u548c Local Storage\u3002\u8fd9\u6837\u7684\u6bd4\u8f83\u624d\u6709\u610f\u4e49\u3002\nJWT \u574a\u95f4\u6d41\u4f20\u7684\u4f18\u52bf \u5728\u4eba\u4eec\u5b89\u5229 JWT \u65f6\uff0c\u5e38\u5e38\u5ba3\u626c\u4ee5\u4e0b\u51e0\u70b9\u597d\u5904\uff1a\n \u6613\u4e8e\u6c34\u5e73\u6269\u5c55 \u6613\u4e8e\u4f7f\u7528 \u66f4\u52a0\u7075\u6d3b \u66f4\u52a0\u5b89\u5168 \u5185\u7f6e\u8fc7\u671f\u65f6\u95f4\u529f\u80fd \u65e0\u9700\u8be2\u95ee\u7528\u6237\u300c\u672c\u7f51\u7ad9\u4f7f\u7528 Cookies\u300d \u9632\u6b62 CSRF \u653b\u51fb \u66f4\u9002\u7528\u4e8e\u79fb\u52a8\u7aef \u9002\u7528\u4e8e\u963b\u6b62 Cookies \u7684\u7528\u6237  \u6211\u5c06\u4f1a\u9010\u6761\u9610\u8ff0\u4ee5\u4e0a\u89c2\u70b9\u4e3a\u4f55\u662f\u9519\u8bef\u6216\u8bef\u5bfc\u6027\u7684\uff0c\u5176\u4e2d\u90e8\u5206\u89e3\u91ca\u53ef\u80fd\u4f1a\u6709\u4e9b\u6a21\u7cca\uff0c\u8fd9\u4e3b\u8981\u662f\u56e0\u4e3a\u8fd9\u4e9b\u300c\u597d\u5904\u300d\u7684\u8868\u8ff0\u672c\u8eab\u5c31\u6bd4\u8f83\u6a21\u7cca\u3002\u4f60\u53ef\u4ee5\u5728\u6587\u672b\u627e\u5230\u6211\u7684\u8054\u7cfb\u65b9\u5f0f\uff0c\u6211\u5c06\u5341\u5206\u4e50\u610f\u5bf9\u66f4\u52a0\u5177\u4f53\u7684\u300c\u597d\u5904\u300d\u8fdb\u884c\u5206\u6790\u9610\u8ff0\u3002\n\u6613\u4e8e\u6c34\u5e73\u6269\u5c55\uff1f \u8fd9\u662f\u5217\u8868\u4e2d\u552f\u4e00\u4e00\u6761\u5728\u6280\u672f\u5c42\u9762\u90e8\u5206\u6b63\u786e\u7684\u300c\u597d\u5904\u300d\uff0c\u4f46\u524d\u63d0\u662f\u4f60\u4f7f\u7528\u7684\u662f\u65e0\u72b6\u6001 JWT Tokens\u3002\u7136\u800c\u4e8b\u5b9e\u4e0a\uff0c\u51e0\u4e4e\u6ca1\u4eba\u9700\u8981\u8fd9\u79cd\u6a2a\u5411\u6269\u5c55\u80fd\u529b\u3002\u6709\u5f88\u591a\u66f4\u7b80\u5355\u7684\u62d3\u5c55\u65b9\u5f0f\uff0c\u9664\u975e\u4f60\u5728\u8fd0\u7ef4\u50cf\u6dd8\u5b9d\u8fd9\u6837\u4f53\u91cf\u7684\u7cfb\u7edf\uff0c\u5426\u5219\u6839\u672c\u4e0d\u9700\u8981\u65e0\u72b6\u6001\u7684\u4f1a\u8bdd\uff08Stateless sessions\uff09\u3002\n\u4e00\u4e9b\u6269\u5c55\u6709\u72b6\u6001\u4f1a\u8bdd\uff08Stateful sessions\uff09\u7684\u4f8b\u5b50\uff1a\n \u5728\u5355\u53f0\u670d\u52a1\u5668\u4e0a\u8fd0\u884c\u591a\u4e2a\u540e\u7aef\u8fdb\u7a0b\uff1a\u53ea\u9700\u5728\u6b64\u670d\u52a1\u5668\u4e0a\u5b89\u88c5 Redis \u670d\u52a1\u7528\u4e8e\u5b58\u50a8 Session \u5373\u53ef\u3002 \u8fd0\u884c\u591a\u53f0\u670d\u52a1\u5668\uff1a\u53ea\u9700\u4e00\u53f0\u4e13\u7528\u7684 Redis \u670d\u52a1\u5668\u7528\u4e8e\u5b58\u50a8 Session \u5373\u53ef\u3002 \u5728\u591a\u96c6\u7fa4\u5185\u8fd0\u884c\u591a\u53f0\u670d\u52a1\u5668\uff1a\u4f1a\u8bdd\u4fdd\u6301\uff08\u53c8\u79f0\uff1a\u7c98\u6ede\u4f1a\u8bdd\uff09\u3002  \u4ee5\u4e0a\u6240\u6709\u573a\u666f\u5728\u73b0\u6709\u8f6f\u4ef6\u7cfb\u7edf\u5185\u90fd\u5177\u5907\u826f\u597d\u7684\u652f\u6301\uff0c\u4f60\u7684\u5e94\u7528\u9700\u8981\u8fdb\u884c\u7279\u6b8a\u5904\u7406\u7684\u53ef\u80fd\u6027\u57fa\u672c\u4e3a\u96f6\u3002\n\u6216\u8bb8\u4f60\u5728\u60f3\uff0c\u5e94\u5f53\u4e3a\u4f60\u7684\u5e94\u7528\u9884\u7559\u66f4\u591a\u8c03\u6574\u7a7a\u95f4\uff0c\u4ee5\u9632\u672a\u6765\u9700\u8981\u67d0\u4e9b\u7279\u6b8a\u64cd\u4f5c\u3002\u4f46\u5b9e\u8df5\u544a\u8bc9\u6211\u4eec\uff0c\u4ee5\u540e\u518d\u66ff\u6362 Session \u673a\u5236\u5e76\u4e0d\u56f0\u96be\uff0c\u552f\u4e00\u7684\u4ee3\u4ef7\u662f\uff0c\u5728\u8fc1\u79fb\u540e\u6240\u6709\u7528\u6237\u5c06\u88ab\u5f3a\u5236\u767b\u51fa\u4e00\u6b21\u3002\u6211\u4eec\u6ca1\u5fc5\u8981\u5728\u524d\u671f\u5b9e\u73b0 JWT\uff0c\u5c24\u5176\u662f\u8003\u8651\u5230\u5b83\u6240\u5e26\u6765\u7684\u8d1f\u9762\u5f71\u54cd\u3002\u6211\u5c06\u5728\u540e\u6587\u8fdb\u884c\u89e3\u91ca\u3002\n\u6613\u4e8e\u4f7f\u7528\uff1f \u8fd9\u4e2a\u771f\u6ca1\u6709\u3002\u4f60\u4e0d\u5f97\u4e0d\u81ea\u884c\u5904\u7406 Session \u7684\u7ba1\u7406\u673a\u5236\uff0c\u65e0\u8bba\u662f\u5ba2\u6237\u7aef\u8fd8\u662f\u670d\u52a1\u7aef\u3002\u7136\u800c\u6807\u51c6\u7684 Session cookies \u5219\u5f00\u7bb1\u5373\u7528\uff0cJWT \u5e76\u6ca1\u6709\u66f4\u7b80\u5355\u3002\n\u66f4\u52a0\u7075\u6d3b\uff1f \u6211\u6682\u65f6\u8fd8\u6ca1\u770b\u5230\u6709\u4eba\u6210\u529f\u5730\u9610\u8ff0\u300cJWT \u5982\u4f55\u66f4\u52a0\u7075\u6d3b\u300d\u3002\u51e0\u4e4e\u6bcf\u4e2a\u4e3b\u6d41\u7684 Session \u5b9e\u73b0\uff0c\u90fd\u5141\u8bb8\u4f60\u76f4\u63a5\u628a\u6570\u636e\u5b58\u50a8\u8fdb Session\uff0c\u8fd9\u8ddf JWT \u7684\u673a\u5236\u5e76\u6ca1\u6709\u5dee\u522b\u3002\u636e\u6211\u6240\u77e5\uff0c\u8fd9\u53ea\u662f\u4e2a\u6d41\u884c\u8bed\u7f62\u4e86\u3002\u5982\u679c\u4f60\u4e0d\u540c\u610f\uff0c\u53ef\u4ee5\u968f\u65f6\u5e26\u4e0a\u793a\u4f8b\u4e0e\u6211\u8054\u7cfb\u3002\n\u66f4\u52a0\u5b89\u5168\uff1f \u4e00\u5927\u6279\u4eba\u8ba4\u4e3a JWT Tokens\u300c\u66f4\u52a0\u5b89\u5168\u300d\uff0c\u7406\u7531\u662f\u4f7f\u7528\u4e86\u52a0\u5bc6\u6280\u672f\u3002\u5b9e\u9645\u4e0a\uff0c\u7b7e\u540d\u540e\u7684 Cookies \u6bd4\u672a\u7b7e\u540d\u7684 Cookies \u540c\u6837\u66f4\u52a0\u5b89\u5168\uff0c\u4f46\u8fd9\u7edd\u4e0d\u662f JWT \u72ec\u6709\u7684\uff0c\u4f18\u79c0\u7684 Session \u5b9e\u73b0\u5747\u4f7f\u7528\u7b7e\u540d\u540e\u7684 Cookies\uff08\u8bd1\u8005\u6ce8\uff1a\u4f8b\u5982 Laravel\uff09\u3002\n\u300c\u4f7f\u7528\u52a0\u5bc6\u6280\u672f\u300d\u5e76\u4e0d\u80fd\u795e\u5947\u5730\u4f7f\u67d0\u4e9b\u4e1c\u897f\u66f4\u52a0\u5b89\u5168\uff0c\u5b83\u5fc5\u987b\u670d\u52a1\u4e8e\u7279\u5b9a\u76ee\u7684\uff0c\u5e76\u4e14\u662f\u9488\u5bf9\u8be5\u76ee\u7684\u7684\u6709\u6548\u89e3\u51b3\u65b9\u6848\u3002\u9519\u8bef\u5730\u4f7f\u7528\u52a0\u5bc6\u53cd\u800c\u53ef\u80fd\u4f1a\u964d\u4f4e\u5b89\u5168\u6027\u3002\n\u53e6\u4e00\u4e2a\u6211\u542c\u8fc7\u5f88\u591a\u6b21\u7684\u5bf9\u4e8e\u300c\u66f4\u52a0\u5b89\u5168\u300d\u7684\u8bba\u8ff0\u662f\u300cJWT \u4e0d\u4f7f\u7528 Cookies \u4f20\u8f93 Tokens\u300d\u3002\u8fd9\u5b9e\u5728\u662f\u592a\u8352\u8c2c\u4e86\uff0cCookie \u53ea\u4e0d\u8fc7\u662f\u4e00\u6761 HTTP \u5934\u4fe1\u606f\uff0c\u4f7f\u7528 Cookies \u5e76\u4e0d\u4f1a\u9020\u6210\u4efb\u4f55\u4e0d\u5b89\u5168\u3002\u4e8b\u5b9e\u4e0a\uff0cCookies \u53d7\u5230\u7279\u522b\u826f\u597d\u7684\u4fdd\u62a4\uff0c\u7528\u4e8e\u9632\u6b62\u6076\u610f\u7684\u5ba2\u6237\u7aef\u4ee3\u7801\u3002\u6211\u5c06\u5728\u540e\u6587\u8fdb\u884c\u9610\u8ff0\u3002\n\u5982\u679c\u62c5\u5fc3\u6709\u4eba\u62e6\u622a\u6389\u4f60\u7684 Session cookies\uff0c\u90a3\u4f60\u5e94\u5f53\u8003\u8651\u4f7f\u7528 TLS\u3002\u5982\u679c\u4e0d\u4f7f\u7528 TLS\uff0c\u4efb\u4f55\u7c7b\u578b\u7684 Session \u673a\u5236\u90fd\u53ef\u80fd\u88ab\u62e6\u622a\uff0c\u5305\u62ec JWT\u3002\n\u5185\u7f6e\u8fc7\u671f\u65f6\u95f4\u529f\u80fd\uff1f \u65e0\u610f\u4e49\uff0c\u53c8\u6ca1\u4ec0\u4e48\u5375\u7528\u7684\u7279\u6027\u3002\u5728\u670d\u52a1\u7aef\u4e5f\u80fd\u5b9e\u73b0\u8fc7\u671f\u63a7\u5236\uff0c\u6709\u4e0d\u5c11 Session \u5b9e\u73b0\u5c31\u662f\u8fd9\u4e48\u505a\u7684\u3002\u5b9e\u9645\u4e0a\uff0c\u670d\u52a1\u7aef\u7684\u8fc7\u671f\u63a7\u5236\u66f4\u52a0\u5408\u7406\uff0c\u8fd9\u6837\u4f60\u7684\u5e94\u7528\u5c31\u53ef\u4ee5\u6e05\u9664\u4e0d\u518d\u9700\u8981\u7684 Session \u6570\u636e\uff1b\u82e5\u4f7f\u7528\u65e0\u72b6\u6001 JWT Tokens \u4e14\u4f9d\u8d56\u4e8e\u5b83\u7684\u8fc7\u671f\u673a\u5236\uff0c\u5219\u65e0\u6cd5\u6267\u884c\u6b64\u64cd\u4f5c\u3002\n\u65e0\u9700\u8be2\u95ee\u7528\u6237\u300c\u672c\u7f51\u7ad9\u4f7f\u7528 Cookies\u300d\uff1f \u5b8c\u5168\u9519\u8bef\u3002\u5e76\u6ca1\u6709\u4ec0\u4e48\u300cCookies \u6cd5\u5f8b\u300d\u2014\u2014 \u6709\u5173 Cookies \u7684\u5404\u79cd\u6cd5\u5f8b\u5b9e\u9645\u4e0a\u6db5\u76d6\u4e86\u4efb\u4f55\u7c7b\u578b\u300c\u5bf9\u67d0\u9879\u670d\u52a1\u7684\u6b63\u5e38\u8fd0\u884c\u975e\u4e25\u683c\u5fc5\u987b\u7684\u6301\u4e45\u6027 ID\u300d\uff0c\u4efb\u4f55\u4f60\u80fd\u60f3\u5230\u7684 Session \u673a\u5236\u90fd\u5305\u62ec\u5728\u5185\u3002\n \u8bd1\u8005\u6ce8\uff1a\u7136\u9e45\u4e2d\u56fd\u5e76\u6ca1\u6709\u3002\n \u7b80\u5355\u6765\u8bf4\uff1a\n \u82e5\u51fa\u4e8e\u7cfb\u7edf\u529f\u80fd\u76ee\u7684\u4f7f\u7528 Session \u6216 Token\uff08\u4f8b\u5982\uff1a\u4fdd\u6301\u7528\u6237\u7684\u767b\u5f55\u6001\uff09\uff0c\u90a3\u4e48\u65e0\u8bba\u600e\u6837\u5b58\u50a8 Session \u5747\u65e0\u9700\u5f81\u5f97\u7528\u6237\u540c\u610f\u3002 \u82e5\u51fa\u4e8e\u5176\u4ed6\u76ee\u7684\u4f7f\u7528 Session \u6216 Token\uff08\u4f8b\u5982\uff1a\u6570\u636e\u5206\u6790\u3001\u8ffd\u8e2a\uff09\uff0c\u90a3\u4e48\u65e0\u8bba\u600e\u6837\u5b58\u50a8 Session \u90fd\u9700\u8981\u8be2\u95ee\u7528\u6237\u662f\u5426\u5141\u8bb8\u3002  \u9632\u6b62 CSRF \u653b\u51fb\uff1f \u8fd9\u4e2a\u771f\u00b7\u771f\u6ca1\u6709\u3002\u5b58\u50a8 JWT Tokens \u7684\u65b9\u5f0f\u5927\u6982\u6709\u4e24\u79cd\uff1a\n \u5b58\u5165 Cookie\uff1a\u4ecd\u7136\u6613\u53d7 CSRF \u653b\u51fb\uff0c\u8fd8\u662f\u9700\u8981\u8fdb\u884c\u7279\u6b8a\u5904\u7406\uff0c\u4fdd\u62a4\u5176\u4e0d\u53d7\u653b\u51fb\u3002 \u5176\u4ed6\u5730\u65b9\uff0c\u4f8b\u5982 Local Storage\uff1a\u867d\u7136\u4e0d\u6613\u53d7\u5230 CSRF \u653b\u51fb\uff0c\u4f46\u4f60\u7684\u7f51\u7ad9\u9700\u8981 JavaScript \u624d\u80fd\u6b63\u5e38\u8bbf\u95ee\uff1b\u5e76\u4e14\u53c8\u5f15\u53d1\u4e86\u53e6\u4e00\u4e2a\u5b8c\u5168\u4e0d\u540c\uff0c\u6216\u8bb8\u66f4\u52a0\u4e25\u91cd\u7684\u6f0f\u6d1e\u3002\u6211\u5c06\u5728\u540e\u6587\u8be6\u7ec6\u8bf4\u660e\u3002  \u9884\u9632 CSRF \u653b\u51fb\u552f\u4e00\u7684\u6b63\u786e\u65b9\u6cd5\uff0c\u5c31\u662f\u4f7f\u7528 CSRF Tokens\u3002Session \u673a\u5236\u4e0e\u6b64\u65e0\u5173\u3002\n\u66f4\u9002\u7528\u4e8e\u79fb\u52a8\u7aef\uff1f \u6beb\u65e0\u6839\u636e\u3002\u76ee\u524d\u6240\u6709\u53ef\u7528\u7684\u6d4f\u89c8\u5668\u51e0\u4e4e\u90fd\u652f\u6301 Cookies\uff0c\u56e0\u6b64\u4e5f\u652f\u6301 Session\u3002\u540c\u6837\uff0c\u4e3b\u6d41\u7684\u79fb\u52a8\u7aef\u5f00\u53d1\u6846\u67b6\u4ee5\u53ca\u4e25\u8c28\u7684 HTTP \u5ba2\u6237\u7aef\u5e93\u90fd\u662f\u5982\u6b64\u3002\u8fd9\u6839\u672c\u4e0d\u662f\u4e2a\u95ee\u9898\u3002\n\u9002\u7528\u4e8e\u963b\u6b62 Cookies \u7684\u7528\u6237\uff1f \u4e0d\u592a\u53ef\u80fd\u3002\u7528\u6237\u901a\u5e38\u4f1a\u963b\u6b62\u4efb\u4f55\u610f\u4e49\u4e0a\u7684\u6301\u4e45\u5316\u6570\u636e\uff0c\u800c\u4e0d\u662f\u53ea\u7981\u6b62 Cookies\u3002\u4f8b\u5982\uff0cLocal Storage \u4ee5\u53ca\u4efb\u4f55\u80fd\u591f\u6301\u4e45\u5316 Session \u7684\u5b58\u50a8\u673a\u5236\uff08\u65e0\u8bba\u662f\u5426\u4f7f\u7528 JWT\uff09\u3002\u4e0d\u7ba1\u4f60\u51fa\u4e8e\u591a\u4e48\u7b80\u5355\u7684\u76ee\u7684\u4f7f\u7528 JWT \u90fd\u65e0\u6d4e\u4e8e\u4e8b\uff0c\u8fd9\u662f\u53e6\u4e00\u4e2a\u5b8c\u5168\u72ec\u7acb\u7684\u95ee\u9898\u4e86\u3002\u53e6\u5916\uff0c\u8bd5\u56fe\u8ba9\u8eab\u4efd\u8ba4\u8bc1\u8fc7\u7a0b\u5728\u6ca1\u6709 Cookies \u7684\u60c5\u51b5\u4e0b\u6b63\u5e38\u8fdb\u884c\uff0c\u57fa\u672c\u6ca1\u620f\u3002\n\u6700\u91cd\u8981\u7684\u662f\uff0c\u7981\u7528\u6389\u6240\u6709 Cookies \u7684\u591a\u6570\u7528\u6237\u90fd\u660e\u767d\u8fd9\u4f1a\u5bfc\u81f4\u8eab\u4efd\u8ba4\u8bc1\u65e0\u6cd5\u4f7f\u7528\uff0c\u4ed6\u4eec\u4f1a\u5355\u72ec\u89e3\u9501\u90a3\u4e9b\u4ed6\u4eec\u6bd4\u8f83\u5173\u5fc3\u7684\u7ad9\u70b9\u3002\u8fd9\u5e76\u4e0d\u662f\u4f60 \u2014\u2014 \u4e00\u4e2a Web \u5f00\u53d1\u8005\u5e94\u5f53\u89e3\u51b3\u7684\u95ee\u9898\u3002\u66f4\u597d\u7684\u65b9\u6848\u662f\uff0c\u5411\u4f60\u7684\u7528\u6237\u4eec\u8be6\u7ec6\u5730\u89e3\u91ca\u4e3a\u4f55\u4f60\u7684\u7f51\u7ad9\u9700\u8981 Cookies \u624d\u80fd\u4f7f\u7528\u3002\nJWT \u7684\u52a3\u52bf \u4ee5\u4e0a\uff0c\u6211\u5df2\u7ecf\u5bf9\u5e38\u89c1\u7684\u8bef\u89e3\u505a\u4e86\u8bf4\u660e\uff0c\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u5b83\u4eec\u662f\u9519\u8bef\u7684\u3002\u4f60\u6216\u8bb8\u5728\u60f3\uff1a\u300c\u8fd9\u597d\u50cf\u4e5f\u6ca1\u4ec0\u4e48\u5927\u4e0d\u4e86\u7684\uff0c\u5373\u4fbf JWT \u65e0\u6cd5\u5e26\u6765\u4efb\u4f55\u597d\u5904\uff0c\u4f46\u4e5f\u4e0d\u4f1a\u9020\u6210\u4ec0\u4e48\u5f71\u54cd\u300d\uff0c\u90a3\u4f60\u771f\u662f\u5927\u9519\u7279\u9519\u4e86\u3002\n\u4f7f\u7528 JWT \u4f5c\u4e3a Session \u673a\u5236\u5b58\u5728\u5f88\u591a\u7f3a\u70b9\uff0c\u5176\u4e2d\u4e00\u90e8\u5206\u4f1a\u9020\u6210\u4e25\u91cd\u7684\u5b89\u5168\u95ee\u9898\u3002\n\u66f4\u8d39\u7a7a\u95f4 JWT Tokens \u5b9e\u9645\u4e0a\u5e76\u4e0d\u300c\u5c0f\u300d\u3002\u5c24\u5176\u662f\u4f7f\u7528\u65e0\u72b6\u6001 JWT \u65f6\uff0c\u6240\u6709\u7684\u6570\u636e\u5c06\u4f1a\u88ab\u76f4\u63a5\u7f16\u7801\u8fdb Tokens \u5185\uff0c\u5f88\u5feb\u5c06\u4f1a\u8d85\u8fc7 Cookies \u6216 URL \u7684\u957f\u5ea6\u9650\u5236\u3002\u4f60\u53ef\u80fd\u5728\u60f3\u5c06\u5b83\u4eec\u5b58\u50a8\u5230 Local Storage\uff0c\u7136\u800c&hellip;\n\u66f4\u4e0d\u5b89\u5168 \u82e5\u5c06 JWT Tokens \u5b58\u50a8\u5230 Cookies \u5185\uff0c\u90a3\u4e48\u5b89\u5168\u6027\u4e0e\u5176\u4ed6 Session \u673a\u5236\u65e0\u5f02\u3002\u4f46\u5982\u679c\u4f60\u5c06 JWT \u5b58\u50a8\u81f3\u5176\u5b83\u5730\u65b9\uff0c\u4f1a\u5bfc\u81f4\u4e00\u4e2a\u65b0\u7684\u6f0f\u6d1e\uff0c\u8be6\u89c1\u672c\u6587\uff0c\u5c24\u5176\u662f\u300cStoring sessions\u300d\u8fd9\u4e00\u90e8\u5206\u3002\n \u4e66\u63a5\u4e0a\u56de\uff1aLocal Storage\uff0c\u4e00\u4e2a HTML5 \u5185\u5f88\u68d2\u7684\u529f\u80fd\uff0c\u4f7f\u6d4f\u89c8\u5668\u652f\u6301 Key\/Value \u5b58\u50a8\u3002\u6240\u4ee5\u6211\u4eec\u5e94\u5f53\u5c06 JWT Tokens \u5b58\u50a8\u5230 Local Storage \u5417\uff1f\u8003\u8651\u5230\u8fd9\u4e9b Tokens \u53ef\u80fd\u8d8a\u6765\u8d8a\u5927\uff0c\u6216\u8bb8\u4f1a\u5f88\u6709\u7528\u3002Cookies \u901a\u5e38\u5728 4k \u5de6\u53f3\u7684\u5b58\u50a8\u65f6\u6bd4\u8f83\u5360\u4f18\u52bf\uff0c\u5bf9\u4e8e\u8f83\u5927\u7684 Tokens\uff0cCookies \u53ef\u80fd\u65e0\u6cd5\u80dc\u4efb\uff0c\u800c Local Storage \u6216\u8bb8\u6210\u4e86\u660e\u786e\u7684\u89e3\u51b3\u65b9\u6848\u3002\u7136\u800c\uff0cLocal Storage \u5e76\u6ca1\u6709\u63d0\u4f9b\u4efb\u4f55\u7c7b\u4f3c Cookies \u7684\u5b89\u5168\u63aa\u65bd\u3002 LocalStorage \u4e0e Cookies \u4e0d\u540c\uff0c\u5e76\u4e0d\u4f1a\u5728\u6bcf\u6b21\u8bf7\u6c42\u65f6\u53d1\u9001\u5b58\u50a8\u7684\u6570\u636e\u3002\u83b7\u53d6\u6570\u636e\u7684\u552f\u4e00\u65b9\u6cd5\u662f\u4f7f\u7528 JavaScript\uff0c\u8fd9\u610f\u5473\u7740\u4efb\u4f55\u653b\u51fb\u8005\u6ce8\u5165\u7684 JavaScript \u811a\u672c\u53ea\u9700\u901a\u8fc7\u5185\u5bb9\u5b89\u5168\u7b56\u7565\u68c0\u67e5\uff0c\u5c31\u80fd\u4efb\u610f\u8bbf\u95ee\u6216\u6cc4\u9732\u6570\u636e\u3002\u4e0d\u5149\u662f\u8fd9\u6837\uff0cJavaScript \u5e76\u4e0d\u5728\u610f\u6216\u8ffd\u8e2a\u6570\u636e\u662f\u5426\u901a\u8fc7 HTTPS \u53d1\u9001\u3002\u5c31 JavaScript \u800c\u8a00\uff0c\u5b83\u5c31\u53ea\u662f\u4e2a\u6570\u636e\u800c\u5df2\uff0c\u6d4f\u89c8\u5668\u4f1a\u50cf\u64cd\u4f5c\u5176\u5b83\u6570\u636e\u4e00\u6837\u6765\u5904\u7406\u5b83\u3002 \u5728\u5386\u4ee3\u5de5\u7a0b\u5e08\u4eec\u7ecf\u5386\u4e86\u5404\u79cd\u9ebb\u70e6\u4e4b\u540e\uff0c\u7ec8\u4e8e\u80fd\u591f\u786e\u4fdd\u6ca1\u6709\u4eba\u53ef\u4ee5\u6076\u610f\u63a5\u89e6\u5230\u6211\u4eec\u7684 Cookies\uff0c\u7136\u800c\u6211\u4eec\u5374\u8bd5\u56fe\u5ffd\u7565\u8fd9\u4e9b\u7ecf\u9a8c\u3002\u8fd9\u5bf9\u6211\u6765\u8bf4\u4f3c\u4e4e\u662f\u5728\u9000\u6b65\u3002\n \u7b80\u5355\u6765\u8bf4\uff0c\u4f7f\u7528 Cookies \u5e76\u4e0d\u662f\u53ef\u9009\u7684\uff0c\u65e0\u8bba\u4f60\u662f\u5426\u91c7\u7528 JWT\u3002\n\u65e0\u6cd5\u5355\u72ec\u9500\u6bc1 \u8fd8\u6709\u66f4\u591a\u5b89\u5168\u95ee\u9898\u3002\u4e0d\u50cf Sessions \u65e0\u8bba\u4f55\u65f6\u90fd\u53ef\u4ee5\u5355\u72ec\u5730\u5728\u670d\u52a1\u7aef\u9500\u6bc1\u3002\u65e0\u72b6\u6001 JWT Tokens \u65e0\u6cd5\u88ab\u5355\u72ec\u7684\u9500\u6bc1\u3002\u6839\u636e JWT \u7684\u8bbe\u8ba1\uff0c\u65e0\u8bba\u600e\u6837 Tokens \u5728\u8fc7\u671f\u524d\u5c06\u4f1a\u4e00\u76f4\u4fdd\u6301\u6709\u6548\u3002\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u8fd9\u610f\u5473\u7740\u5728\u68c0\u6d4b\u5230\u653b\u51fb\u65f6\uff0c\u4f60\u5374\u4e0d\u80fd\u9500\u6bc1\u653b\u51fb\u8005\u7684 Session\u3002\u540c\u6837\uff0c\u5728\u7528\u6237\u4fee\u6539\u5bc6\u7801\u540e\uff0c\u4e5f\u65e0\u6cd5\u9500\u6bc1\u65e7\u7684 Sessions\u3002\n\u5bf9\u6b64\uff0c\u6211\u4eec\u51e0\u4e4e\u65e0\u80fd\u4e3a\u529b\uff0c\u9664\u975e\u91cd\u65b0\u6784\u5efa\u590d\u6742\u4e14\u6709\u72b6\u6001\uff08Stateful\uff09\u7684\u57fa\u7840\u8bbe\u65bd\u6765\u660e\u786e\u5730\u68c0\u6d4b\u6216\u62d2\u7edd\u7279\u5b9a Session\uff0c\u5426\u5219\u5c06\u65e0\u6cd5\u7ed3\u675f\u4f1a\u8bdd\u3002\u4f46\u8fd9\u5b8c\u5168\u8fdd\u80cc\u4e86\u4f7f\u7528\u65e0\u72b6\u6001 JWT Tokens \u7684\u6700\u521d\u76ee\u7684\u3002\n\u6570\u636e\u5ef6\u8fdf \u4e0e\u4e0a\u6587\u7684\u5b89\u5168\u95ee\u9898\u7c7b\u4f3c\uff0c\u8fd8\u6709\u53e6\u4e00\u4e2a\u6f5c\u5728\u7684\u5b89\u5168\u9690\u60a3\u3002\u5c31\u50cf\u7f13\u5b58\uff0c\u5728\u65e0\u72b6\u6001 Tokens \u5185\u5b58\u50a8\u7684\u6570\u636e\u6700\u7ec8\u4f1a\u300c\u8fc7\u65f6\u300d\uff0c\u4e0d\u518d\u53cd\u6620\u6570\u636e\u5e93\u5185\u6700\u65b0\u7684\u6570\u636e\u3002\n\u8fd9\u610f\u5473\u7740\uff0cTokens \u5185\u4fdd\u7559\u7684\u53ef\u80fd\u662f\u8fc7\u671f\u7684\u4fe1\u606f\uff0c\u4f8b\u5982\uff1a\u7528\u6237\u5728\u4e2a\u4eba\u4fe1\u606f\u9875\u9762\u4fee\u6539\u8fc7\u7684\u65e7 URL\u3002\u66f4\u4e25\u8083\u70b9\u8bb2\uff0c\u4e5f\u53ef\u80fd\u662f\u4e2a\u5177\u5907 admin \u6743\u9650\u7684 Token\uff0c\u5373\u4f7f\u4f60\u5df2\u7ecf\u5e9f\u9664\u4e86 admin \u6743\u9650\u3002\u56e0\u4e3a\u65e0\u6cd5\u9500\u6bc1\u8fd9\u4e9b Tokens\uff0c\u6240\u4ee5\u9762\u5bf9\u9700\u8981\u79fb\u9664\u7684\u7ba1\u7406\u5458\u6743\u9650\uff0c\u9664\u975e\u5173\u95ed\u6574\u4e2a\u7cfb\u7edf\uff0c\u522b\u65e0\u4ed6\u6cd5\u3002\n\u5b9e\u73b0\u5e93\u7f3a\u4e4f\u751f\u4ea7\u73af\u5883\u9a8c\u8bc1\u6216\u538b\u6839\u4e0d\u5b58\u5728 \u4f60\u6216\u8bb8\u5728\u60f3\uff0c\u4ee5\u4e0a\u7684\u8fd9\u4e9b\u95ee\u9898\u90fd\u662f\u56f4\u7ed5\u7740\u300c\u65e0\u72b6\u6001 JWT\u300d\u5c55\u5f00\u7684\uff0c\u8fd9\u79cd\u8bf4\u6cd5\u5927\u90e8\u5206\u60c5\u51b5\u662f\u5bf9\u7684\u3002\u7136\u800c\uff0c\u4f7f\u7528\u6709\u72b6\u6001 Tokens \u4e0e\u4f20\u7edf\u7684 Session cookies \u57fa\u672c\u4e0a\u662f\u7b49\u6548\u7684&hellip; \u4f46\u5374\u7f3a\u4e4f\u751f\u4ea7\u73af\u5883\u7684\u5927\u91cf\u9a8c\u8bc1\u3002\n\u73b0\u5b58\u7684 Session \u5b9e\u73b0\uff08\u4f8b\u5982\u9002\u7528\u4e8e Express \u7684 express-session\uff09\u5df2\u7ecf\u88ab\u7528\u4e8e\u751f\u4ea7\u73af\u5883\u5f88\u591a\u5f88\u591a\u5e74\uff0c\u5b83\u4eec\u7684\u5b89\u5168\u6027\u4e5f\u7ecf\u8fc7\u4e86\u5927\u91cf\u7684\u6539\u826f\u3002\u5018\u82e5\u4f7f\u7528 JWT \u4f5c\u4e3a Session cookies \u7684\u4e34\u65f6\u66ff\u4ee3\u54c1\uff0c\u4f60\u5c06\u65e0\u6cd5\u4eab\u53d7\u5230\u8fd9\u4e9b\u597d\u5904\uff0c\u5e76\u4e14\u5fc5\u987b\u4e0d\u65ad\u6539\u8fdb\u81ea\u5df1\u7684\u5b9e\u73b0\uff08\u5728\u6b64\u8fc7\u7a0b\u4e2d\u5f88\u5bb9\u6613\u5f15\u5165\u6f0f\u6d1e\uff09\uff0c\u6216\u4f7f\u7528\u7b2c\u4e09\u65b9\u7684\u5b9e\u73b0\uff0c\u5c3d\u7ba1\u8fd8\u6ca1\u6709\u5728\u771f\u5b9e\u4e16\u754c\u91cc\u5927\u91cf\u5e94\u7528\u3002\n \u8bd1\u8005\u6ce8\uff1a\u5b9e\u9645\u4e0a\uff0cLaravel Passport \u4fbf\u662f\u4f7f\u7528\u7c7b\u4f3c\u300c\u6709\u72b6\u6001 JWT\u300d\u7684\u65b9\u5f0f\u6765\u5b58\u50a8 OAuth Access Token\u3002\u5e78\u8fd0\u7684\u662f\uff0cPassport \u5df2\u7ecf\u6709\u4e0d\u5c11\u5b9e\u9645\u5e94\u7528\uff0c\u4e14\u4e0d\u5b8c\u5168\u4f9d\u8d56\u4e8e JWT\u3002\n \u7ed3\u8bba \u65e0\u72b6\u6001 JWT Tokens \u65e0\u6cd5\u88ab\u5355\u72ec\u5730\u9500\u6bc1\u6216\u66f4\u65b0\uff0c\u53d6\u51b3\u4e8e\u4f60\u5982\u4f55\u5b58\u50a8\uff0c\u53ef\u80fd\u8fd8\u4f1a\u5bfc\u81f4\u957f\u5ea6\u95ee\u9898\u3001\u5b89\u5168\u9690\u60a3\u3002\u6709\u72b6\u6001 JWT Tokens \u5728\u529f\u80fd\u65b9\u9762\u4e0e Session cookies \u65e0\u5f02\uff0c\u4f46\u7f3a\u4e4f\u751f\u4ea7\u73af\u5883\u7684\u9a8c\u8bc1\u3001\u7ecf\u8fc7\u5927\u91cf Review \u7684\u5b9e\u73b0\uff0c\u4ee5\u53ca\u826f\u597d\u7684\u5ba2\u6237\u7aef\u652f\u6301\u3002\n\u9664\u975e\uff0c\u4f60\u5de5\u4f5c\u5728\u50cf BAT \u90a3\u6837\u89c4\u6a21\u7684\u516c\u53f8\uff0c\u5426\u5219\u6ca1\u4ec0\u4e48\u4f7f\u7528 JWT \u4f5c\u4e3a Session \u673a\u5236\u7684\u7406\u7531\u3002\u8fd8\u662f\u76f4\u63a5\u7528 Session \u5427\u3002\n\u6240\u4ee5&hellip; JWT \u9002\u5408\u505a\u4ec0\u4e48\uff1f \u5728\u672c\u6587\u4e4b\u521d\uff0c\u6211\u5c31\u63d0\u5230 JWT \u867d\u7136\u4e0d\u9002\u5408\u4f5c\u4e3a Session \u673a\u5236\uff0c\u4f46\u5728\u5176\u5b83\u65b9\u9762\u7684\u786e\u6709\u5b83\u7684\u7528\u6b66\u4e4b\u5730\u3002\u8be5\u4e3b\u5f20\u4f9d\u65e7\u6210\u7acb\uff0cJWT \u7279\u522b\u6709\u6548\u7684\u4f7f\u7528\u4f8b\u5b50\u901a\u5e38\u662f\u4f5c\u4e3a\u4e00\u6b21\u6027\u7684\u6388\u6743\u4ee4\u724c\u3002\n\u5f15\u7528 JSON Web Token specification\uff1a\n JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. [&hellip;] enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and\/or encrypted.\n \u5728\u6b64\u4e0a\u4e0b\u6587\u4e2d\uff0c\u300cClaim\u300d\u53ef\u80fd\u662f\u4e00\u6761\u300c\u547d\u4ee4\u300d\uff0c\u4e00\u6b21\u6027\u7684\u8ba4\u8bc1\uff0c\u6216\u662f\u57fa\u672c\u4e0a\u80fd\u591f\u7528\u4ee5\u4e0b\u53e5\u5b50\u63cf\u8ff0\u7684\u4efb\u4f55\u60c5\u51b5\uff1a\n \u4f60\u597d\uff0c\u670d\u52a1\u5668 B\uff0c\u670d\u52a1\u5668 A \u544a\u8bc9\u6211\u6211\u53ef\u4ee5 &lt; &hellip;Claim&hellip; &gt;\uff0c\u8fd9\u662f\u6211\u7684\u8bc1\u636e\uff1a&lt; &hellip;\u5bc6\u94a5&hellip; &gt;\u3002\n \u4e3e\u4e2a\u4f8b\u5b50\uff0c\u4f60\u6709\u4e2a\u6587\u4ef6\u670d\u52a1\uff0c\u7528\u6237\u5fc5\u987b\u8ba4\u8bc1\u540e\u624d\u80fd\u4e0b\u8f7d\u6587\u4ef6\uff0c\u4f46\u6587\u4ef6\u672c\u8eab\u5b58\u50a8\u5728\u4e00\u53f0\u5b8c\u5168\u5206\u79bb\u4e14\u65e0\u72b6\u6001\u7684\u300c\u4e0b\u8f7d\u670d\u52a1\u5668\u300d\u5185\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u53ef\u80fd\u60f3\u8981\u300c\u5e94\u7528\u670d\u52a1\u5668\uff08\u670d\u52a1\u5668 A\uff09\u300d\u9881\u53d1\u4e00\u6b21\u6027\u7684\u300c\u4e0b\u8f7d Tokens\u300d\uff0c\u7528\u6237\u80fd\u591f\u4f7f\u7528\u5b83\u53bb\u300c\u4e0b\u8f7d\u670d\u52a1\u5668\uff08\u670d\u52a1\u5668 B\uff09\u300d\u83b7\u53d6\u9700\u8981\u7684\u6587\u4ef6\u3002\n\u4ee5\u8fd9\u79cd\u65b9\u5f0f\u4f7f\u7528 JWT\uff0c\u5177\u5907\u51e0\u4e2a\u660e\u786e\u7684\u7279\u6027\uff1a\n Tokens \u751f\u547d\u671f\u8f83\u77ed\u3002\u5b83\u4eec\u53ea\u9700\u5728\u51e0\u5206\u949f\u5185\u53ef\u7528\uff0c\u8ba9\u5ba2\u6237\u7aef\u80fd\u591f\u5f00\u59cb\u4e0b\u8f7d\u3002 Tokens \u4ec5\u5355\u6b21\u4f7f\u7528\u3002\u5e94\u7528\u670d\u52a1\u5668\u5e94\u5f53\u5728\u6bcf\u6b21\u4e0b\u8f7d\u65f6\u9881\u53d1\u65b0\u7684 Token\u3002\u6240\u4ee5\u4efb\u4f55 Token \u53ea\u7528\u4e8e\u4e00\u6b21\u8bf7\u6c42\u5c31\u4f1a\u88ab\u629b\u5f03\uff0c\u4e0d\u5b58\u5728\u4efb\u4f55\u6301\u4e45\u5316\u7684\u72b6\u6001\u3002 \u5e94\u7528\u670d\u52a1\u5668\u4f9d\u65e7\u4f7f\u7528 Sessions\u3002\u4ec5\u4ec5\u4e0b\u8f7d\u670d\u52a1\u5668\u4f7f\u7528 Tokens \u6765\u6388\u6743\u6bcf\u6b21\u4e0b\u8f7d\uff0c\u56e0\u4e3a\u5b83\u4e0d\u9700\u8981\u4efb\u4f55\u6301\u4e45\u5316\u72b6\u6001\u3002  \u6b63\u5982\u4ee5\u4e0a\u4f60\u6240\u770b\u5230\u7684\uff0c\u7ed3\u5408 Sessions \u548c JWT Tokens \u6709\u7406\u6709\u636e\u3002\u5b83\u4eec\u5206\u522b\u62e5\u6709\u5404\u81ea\u7684\u76ee\u7684\uff0c\u6709\u65f6\u5019\u4f60\u9700\u8981\u4e24\u8005\u4e00\u8d77\u4f7f\u7528\u3002\u53ea\u662f\u4e0d\u8981\u628a JWT \u7528\u4f5c \u6301\u4e45\u7684\u3001\u957f\u671f\u7684 \u6570\u636e\u5c31\u597d\u3002\n \u62d3\u5c55\u9605\u8bfb\uff1ahttps:\/\/paragonie.com\/blog\/2017\/03\/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid\n","permalink":"https:\/\/wi1dcard.dev\/posts\/stop-using-jwt-for-sessions\/","summary":"<p>JSON Web Tokens\uff0c\u53c8\u79f0 <code>JWT<\/code>\u3002\u672c\u6587\u4f5c\u8005\u5c06\u8be6\u89e3\uff1a\u4e3a\u4f55 JWT \u4e0d\u9002\u5408\u5b58\u50a8 Session\uff0c\u4ee5\u53ca JWT \u5f15\u53d1\u7684\u5b89\u5168\u9690\u60a3\u3002\u671b\u5404\u4f4d\u4f7f\u7528\u524d\u4e09\u601d\u3002<\/p>","title":"\u505c\u6b62\u4f7f\u7528 JWT \u4f5c\u4e3a Session \u7cfb\u7edf"},{"content":"\u539f\u6765 Travis CI \u5b98\u65b9\u4e00\u76f4\u63d0\u4f9b\u7740\u90e8\u7f72\u5230 GitHub Pages \u7684\u65b9\u5f0f&hellip;\n\u90a3\u4e48\u90a3\u4e9b\u626f\u86cb\u7684\u6559\u7a0b\u53ef\u4ee5\u4e00\u8fb9\u73a9\u53bb\u4e86\u3002\n\u4eca\u5929\u840c\u751f\u4e00\u4e2a\u60f3\u6cd5\uff0c\u4f7f\u7528 Travis CI + Qshell\uff08\u4e03\u725b\u4e91\u5b98\u65b9 CLI \u5ba2\u6237\u7aef\uff09\u5b9e\u73b0\u6bcf\u6b21\u90e8\u7f72\u535a\u5ba2\uff0c\u81ea\u52a8\u5c06\u7b80\u5386 HTML \u9875\u9762\u6e32\u67d3\u6210 PDF \u5e76\u4e0a\u4f20\u81f3\u4e03\u725b\u4ee5\u4f9b\u4e0b\u8f7d\u7684\u529f\u80fd\u3002\n\u5728\u9605\u8bfb Travis \u5b98\u65b9\u6587\u6863\u7684\u65f6\u5019\u5076\u7136\u770b\u5230\uff1a\n More than running tests:\ndeploy to GitHub pages\n \u8fdb\u53bb\u53d1\u73b0 Travis \u4e00\u76f4\u4ee5\u6765\u5c31\u63d0\u4f9b\u4e86\u7b80\u6613\u7684 Deploy \u96c6\u6210\uff0c\u9664\u4e86 Pages \u8fd8\u6709 S3 \u7b49\u670d\u52a1\u53ef\u4ee5\u5f00\u7bb1\u5373\u7528\u3002\n\u7136\u540e\u53c8\u7784\u4e86\u4e00\u773c Travis \u6587\u6863\u4ed3\u5e93\u7684 File History\uff0c\u53d1\u73b0&hellip; Emmmm\u3002\n\u539f\u6765\u8fd9\u4e2a\u529f\u80fd\u4e00\u76f4\u90fd\u5728\uff0c\u6700\u65e9\u80fd\u8ffd\u6eaf\u5230 2016 \u5e74\u4e86\u3002\n\u9614\u6015\u9614\u6015\u3002\u7136\u9e45\u5373\u4f7f\u8fd9\u6837\uff0c\u7f51\u7edc\u4e0a\u8fd8\u6d41\u4f20\u7740\u4e00\u5927\u6279\u4e71\u4e03\u516b\u7cdf\u300c\u8bbe\u7f6e SSH \u5bc6\u94a5\u300d\u3001\u300c\u624b\u52a8\u8fdb\u884c Commit \u548c Push\u300d \u7684\u4e2d\u6587\u6559\u7a0b\uff08\u5c24\u5176\u767e\u5ea6\uff09\u3002\u7b80\u76f4\u5bb3\u4eba\u4e0d\u6d45\u3002\n\u7531\u6b64\u53ef\u89c1\uff0c\u4e0d\u8981\u76f8\u4fe1\u91ce\u8def\u5b50\u7684\u5947\u8469\u6559\u7a0b\uff0c\u6709\u80fd\u529b\u8fd8\u662f\u9605\u8bfb\u5b98\u65b9\u6587\u6863\u6bd4\u8f83\u597d\u3002\n\u8d8a\u6765\u8d8a\u89c9\u5f97\u65e5\u5e38\u79d1\u5b66\u4e0a\u7f51\u662f\u7a0b\u5e8f\u5458\u7684\u5fc5\u5907\u6280\u80fd\u4e4b\u4e00\uff0c\u5c24\u5176\u662f\u5728\u5982\u4eca\u7684\u5927\u73af\u5883\u4e0b\u3002\n\u53e6\uff0c\u4eca\u5929\u770b\u5230\u4e00\u56fe\uff0c\u6709\u70b9\u611f\u60f3\uff0c\u8bb0\u5f55\u4e00\u4e0b\uff1a\n","permalink":"https:\/\/wi1dcard.dev\/posts\/deploy-github-pages-with-travis-ci\/","summary":"<p>\u539f\u6765 Travis CI \u5b98\u65b9\u4e00\u76f4\u63d0\u4f9b\u7740\u90e8\u7f72\u5230 GitHub Pages \u7684\u65b9\u5f0f&hellip;<\/p>\n<p>\u90a3\u4e48\u90a3\u4e9b\u626f\u86cb\u7684\u6559\u7a0b\u53ef\u4ee5\u4e00\u8fb9\u73a9\u53bb\u4e86\u3002<\/p>","title":"\u4f7f\u7528 Travis \u90e8\u7f72 GitHub Pages"},{"content":"humbug\/box \u662f\u4e00\u6b3e\u5feb\u901f\u7684\u3001\u96f6\u914d\u7f6e\u7684 PHAR \u6253\u5305\u5de5\u5177\u3002\n\u8fd8\u8bb0\u5f97\u524d\u4e9b\u5929\u7684\u300aSMProxy,\u8ba9\u4f60\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5feb\u4e09\u500d\uff01\u300b\u5417\uff0c\u8be5\u9879\u76ee\u7684 PHAR \u4fbf\u662f\u4f7f\u7528 Box \u6253\u5305\u5b8c\u6210\u7684\u3002\n\u8be5\u9879\u76ee\u662f box-project\/box2 \u7684 Fork \u5206\u652f\uff0c\u539f\u9879\u76ee\u5df2\u7ecf\u4e0d\u518d\u7ef4\u62a4\u3002\u65b0\u9879\u76ee\u7684\u4f5c\u8005\u547c\u5401\u6211\u4eec\u652f\u6301\u8be5 Fork\u3002\nBox \u7684\u53ef\u914d\u7f6e\u9879\u6709\u5f88\u591a\uff0c\u4e3a\u4e86\u80fd\u591f\u5feb\u901f\u5e2e\u52a9\u5927\u5bb6\u4e86\u89e3\u7528\u6cd5\uff0c\u63a5\u4e0b\u6765\u6211\u5c06\u4f7f\u7528 SMProxy \u7684 box.json \u4f5c\u4e3a\u4f8b\u5b50\u7ed9\u5927\u5bb6\u505a\u4e00\u4e2a\u7b80\u5355\u7684\u4ecb\u7ecd\u3002\n \u63a8\u8350\u4e00\u7bc7\u9884\u5907\u77e5\u8bc6\uff0c\u53ef\u4ee5\u5e2e\u4f60\u7b80\u5355\u4e86\u89e3 PHAR \u7684\u90e8\u5206\u7528\u9014\uff1a\u4f7f\u7528 phar \u4e0a\u7ebf\u4f60\u7684\u4ee3\u7801\u5305\u3002\n \u9996\u5148\uff0c\u6b63\u5982 Box \u4f5c\u8005\u7684\u63cf\u8ff0\uff1a\n Fast, zero config application bundler with PHARs.\n \u6211\u4eec\u9ed8\u8ba4\u65e0\u9700\u4efb\u4f55\u914d\u7f6e\uff0c\u5728\u4f60\u7684 PHP \u5e94\u7528\u7684\u6839\u76ee\u5f55\u6267\u884c\uff1a\ncomposer require humbug\/box vendor\/bin\/box compile \u5373\u53ef\u751f\u6210\u4e00\u4e2a\u57fa\u672c\u7684 PHAR \u5305\u6587\u4ef6\u3002\nBox \u7684\u914d\u7f6e\u6587\u4ef6\u4e3a\u5e94\u7528\u6839\u76ee\u5f55\u7684 box.json\uff0c\u4f8b\u5982 SMProxy \u9879\u76ee\u7684\u8be5\u6587\u4ef6\u5185\u5bb9\u4e3a\uff1a\n{ &#34;main&#34;: &#34;bin\/SMProxy&#34;, &#34;output&#34;: &#34;SMProxy.phar&#34;, &#34;directories&#34;: [ &#34;bin&#34;, &#34;src&#34; ], &#34;finder&#34;: [ { &#34;notName&#34;: &#34;\/LICENSE|.*\\\\.md|.*\\\\.dist|composer\\\\.json|composer\\\\.lock\/&#34;, &#34;exclude&#34;: [ &#34;doc&#34;, &#34;docs&#34;, &#34;test&#34;, &#34;test_old&#34;, &#34;tests&#34;, &#34;Tests&#34;, &#34;vendor-bin&#34; ], &#34;in&#34;: &#34;vendor&#34; }, { &#34;name&#34;: &#34;composer.json&#34;, &#34;in&#34;: &#34;.&#34; } ], &#34;compression&#34;: &#34;NONE&#34;, &#34;compactors&#34;: [ &#34;KevinGH\\\\Box\\\\Compactor\\\\Json&#34;, &#34;KevinGH\\\\Box\\\\Compactor\\\\Php&#34; ], &#34;git&#34;: &#34;phar-version&#34; }  main \u7528\u4e8e\u8bbe\u5b9a\u5e94\u7528\u7684\u5165\u53e3\u6587\u4ef6\uff0c\u4e5f\u5c31\u662f\u6253\u5305 PHAR \u540e\uff0c\u76f4\u63a5\u8fd0\u884c\u8be5 PHAR \u5305\u6240\u6267\u884c\u7684\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u5728\u67d0\u79cd\u610f\u4e49\u4e0a\u7406\u89e3\u4e3a index.php\u3002 output \u7528\u4e8e\u8bbe\u5b9a PHAR \u7684\u8f93\u51fa\u6587\u4ef6\uff0c\u53ef\u4ee5\u5305\u542b\u76ee\u5f55\uff0c\u76f8\u5bf9\u8def\u5f84\u6216\u7edd\u5bf9\u8def\u5f84\u3002 directories \u7528\u4e8e\u6307\u5b9a\u6253\u5305\u7684 PHP \u6e90\u7801\u76ee\u5f55\u3002 finder \u914d\u7f6e\u76f8\u5bf9\u6bd4\u8f83\u590d\u6742\uff0c\u5e95\u5c42\u662f\u4f7f\u7528 Symfony\/Finder \u5b9e\u73b0\uff0c\u4e0e PHP-CS-Fixer \u7684 Finder \u89c4\u5219\u7c7b\u4f3c\u3002\u5728\u4ee5\u4e0a\u4f8b\u5b50\u4e2d\uff0c\u5305\u542b\u4e24\u4e2a Finder\uff1b\u7b2c\u4e00\u4e2a\u5b9a\u4e49\u5728 vendor \u6587\u4ef6\u5939\u5185\uff0c\u6392\u9664\u6307\u5b9a\u540d\u79f0\u7684\u6587\u4ef6\u548c\u76ee\u5f55\uff1b\u7b2c\u4e8c\u4e2a\u8868\u793a\u5305\u542b\u5e94\u7528\u6839\u76ee\u5f55\u7684 composer.json\u3002 compression \u7528\u4e8e\u8bbe\u5b9a PHAR \u6587\u4ef6\u6253\u5305\u65f6\u4f7f\u7528\u7684\u538b\u7f29\u7b97\u6cd5\u3002\u53ef\u9009\u503c\u6709\uff1aGZ\uff08\u6700\u5e38\u7528\uff09 \/ BZ2 \/ NONE\uff08\u9ed8\u8ba4\uff09\u3002\u4f46\u6709\u4e00\u70b9\u9700\u8981\u6ce8\u610f\uff1a\u4f7f\u7528 GZ \u8981\u6c42\u8fd0\u884c PHAR \u7684 PHP \u73af\u5883\u5df2\u542f\u7528 Gzip \u6269\u5c55\uff0c\u5426\u5219\u4f1a\u9020\u6210\u62a5\u9519\u3002 compactors \u7528\u4e8e\u8bbe\u5b9a\u538b\u7f29\u5668\uff0c\u4f46\u6b64\u5904\u7684\u538b\u7f29\u5668\u4e0d\u540c\u4e8e\u4e0a\u6587\u6240\u4ecb\u7ecd\u7684 compression\uff1b\u4e00\u4e2a\u538b\u7f29\u5668\u7c7b\u5b9e\u4f8b\u53ef\u538b\u7f29\u7279\u5b9a\u6587\u4ef6\u7c7b\u578b\uff0c\u964d\u4f4e\u6587\u4ef6\u5927\u5c0f\uff0c\u4f8b\u5982\u4ee5\u4e0b Box \u81ea\u5e26\u7684\u538b\u7f29\u5668\uff1a  KevinGH\\Box\\Compactor\\Json\uff1a\u538b\u7f29 JSON \u6587\u4ef6\uff0c\u53bb\u9664\u7a7a\u683c\u548c\u7f29\u8fdb\u7b49\u3002 KevinGH\\Box\\Compactor\\Php\uff1a\u538b\u7f29 PHP \u6587\u4ef6\uff0c\u53bb\u9664\u6ce8\u91ca\u548c PHPDoc \u7b49\u3002 KevinGH\\Box\\Compactor\\PhpScoper\uff1a\u4f7f\u7528 humbug\/php-scoper \u9694\u79bb\u4ee3\u7801\u3002   git \u7528\u4e8e\u8bbe\u5b9a\u4e00\u4e2a\u300c\u5360\u4f4d\u7b26\u300d\uff0c\u6253\u5305\u65f6\u5c06\u4f1a\u626b\u63cf\u6587\u4ef6\u5185\u662f\u5426\u542b\u6709\u6b64\u5904\u5b9a\u4e49\u7684\u5360\u4f4d\u7b26\uff0c\u82e5\u5b58\u5728\u5c06\u4f1a\u66ff\u6362\u4e3a\u4f7f\u7528 Git \u6700\u65b0 Tag \u548c Commit \u751f\u6210\u7684\u7248\u672c\u53f7\uff08\u4f8b\u5982 2.0.0 \u6216 2.0.0@e558e33\uff09\u3002\u4f60\u53ef\u4ee5\u53c2\u8003 \u8fd9\u91cc \u7684\u4ee3\u7801\u6765\u66f4\u52a0\u6df1\u5165\u5730\u7406\u89e3\u8be5\u7528\u6cd5\u3002  \u6211\u76ee\u524d\u5e38\u7528\u7684\u914d\u7f6e\u5927\u6982\u5c31\u662f\u8fd9\u4e9b\uff0c\u5f3a\u529b\u63a8\u8350\u770b\u770b\u5b98\u65b9\u7684 \u914d\u7f6e\u6587\u6863 \u6765\u4e86\u89e3\u66f4\u591a\u7684\u914d\u7f6e\u9879\u3001\u793a\u4f8b\u548c\u9ed8\u8ba4\u503c\uff0c\u4ee5\u53ca\u5b83\u4eec\u7684\u7528\u6cd5\uff1b\u601d\u8def\u6e05\u6670\u3001\u7b80\u660e\u627c\u8981\u3002\n\u6700\u540e\uff0c\u63a8\u8350\u5173\u6ce8 SMProxy\uff0c\u82f1\u6587\u6587\u6863\u548c\u4e0a\u6587\u4ecb\u7ecd\u7684 PHAR \u6253\u5305\u90e8\u5206\uff0c\u57fa\u672c\u90fd\u662f\u7531\u6211\u5b8c\u6210\uff0c\u6709\u4efb\u4f55\u7591\u95ee\u6b22\u8fce\u901a\u8fc7 Issue \u8054\u7cfb\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/packaging-apps-with-phar\/","summary":"<p><a href=\"https:\/\/github.com\/humbug\/box\" target=\"_blank\">humbug\/box<\/a> \u662f\u4e00\u6b3e\u5feb\u901f\u7684\u3001\u96f6\u914d\u7f6e\u7684 PHAR \u6253\u5305\u5de5\u5177\u3002<\/p>\n<p>\u8fd8\u8bb0\u5f97\u524d\u4e9b\u5929\u7684\u300a<a href=\"https:\/\/laravel-china.org\/articles\/19742\" target=\"_blank\">SMProxy,\u8ba9\u4f60\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5feb\u4e09\u500d\uff01<\/a>\u300b\u5417\uff0c\u8be5\u9879\u76ee\u7684 PHAR \u4fbf\u662f\u4f7f\u7528 Box \u6253\u5305\u5b8c\u6210\u7684\u3002<\/p>","title":"\u5c06 PHP \u5e94\u7528\u5feb\u901f\u6253\u5305\u4e3a PHAR"},{"content":"chubin\/wttr.in \u662f\u4e00\u6b3e\u9762\u5411\u547d\u4ee4\u884c\u7684\u5929\u6c14\u9884\u62a5\u670d\u52a1\uff0c\u652f\u6301\u591a\u79cd HTTP \u5ba2\u6237\u7aef\u8fdb\u884c\u8bf7\u6c42\uff0c\u4f8b\u5982\uff1acurl \/ httpie \/ wget \u7b49\u3002\u8be5\u9879\u76ee\u7684\u5b98\u65b9\u63cf\u8ff0\u4fbf\u662f\uff1a\n The right way to check the weather.\n \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u4e0d\u9700\u8981\u5b89\u88c5\u989d\u5916\u7684\u5ba2\u6237\u7aef\uff1b\u5728\u4efb\u4f55\u5177\u5907 curl \u7684\u7535\u8111\u4e0a\u6267\u884c curl wttr.in \u5373\u53ef\u3002\n\u4f8b\u5982\uff1a\n\u8be5\u9879\u76ee\u5c06\u4f1a\u901a\u8fc7 IP \u5224\u65ad\u4f60\u7684\u7269\u7406\u5730\u5740\uff0c\u5e76\u5c55\u793a\u5b9e\u65f6\u4ee5\u53ca\u672a\u6765\u7684\u5929\u6c14\u3002\u5176\u4e2d ?lang=zh \u7528\u4e8e\u8bbe\u5b9a\u8bed\u8a00\u53c2\u6570\u4e3a\u4e2d\u6587\uff0c\u9ed8\u8ba4\u8bed\u8a00\u4e3a\u82f1\u6587\u3002\n\u53e6\u5916\uff0c\u5b98\u65b9\u5728 README \u5185\u8fd8\u7ed9\u51fa\u4e86\u4e00\u4e2a\u5b9e\u5b9e\u5728\u5728\u7684\u300c\u5b9e\u65f6\u300d\u56fe\u7247\u4f8b\u5b50\uff1a\n\u4f60\u4e5f\u53ef\u4ee5\u901a\u8fc7\u6307\u5b9a\u53c2\u6570\u6765\u83b7\u53d6\u7279\u5b9a\u5730\u70b9\u7684\u5929\u6c14\uff0c\u4f8b\u5982\uff1a\n$ curl wttr.in\/Beijing $ curl wttr.in\/\u5317\u4eac \u751a\u81f3\u53ef\u4ee5\u901a\u8fc7 IATA \u673a\u573a\u4ee3\u7801\uff08\u7531\u4e09\u4f4d\u5b57\u6bcd\u7ec4\u6210\uff09\u6765\u67e5\u8be2\u673a\u573a\u5929\u6c14\uff1a\n$ curl wttr.in\/pek # \u5317\u4eac\u9996\u90fd\u56fd\u9645\u673a\u573a $ curl wttr.in\/sha # \u4e0a\u6d77\u8679\u6865\u56fd\u9645\u673a\u573a \u53e6\u5916\uff0c\u5982\u679c\u4f60\u7684 IP \u6765\u81ea\u7f8e\u56fd\uff08\u5c31\u50cf\u6211\u6700\u4e0a\u9762\u7684\u622a\u56fe\u90a3\u6837\uff09\uff0c\u9ed8\u8ba4\u5c06\u4f1a\u4f7f\u7528\u7f8e\u56fd\u5236\u7684\u6e29\u5ea6\u5355\u4f4d\u3002\u4f60\u53ef\u4ee5\u901a\u8fc7\u5728\u7ed3\u5c3e\u6dfb\u52a0 m \u6216 u \u53c2\u6570\u6765\u8bbe\u5b9a\u4f7f\u7528\u516c\u5236\u5355\u4f4d\u6216\u7f8e\u56fd\u5355\u4f4d\uff0c\u4f8b\u5982\uff1a\n$ curl &quot;wttr.in\/Beijing?u&quot; $ curl &quot;wttr.in\/Beijing?m&quot; \u5927\u6982\u5c31\u662f\u8fd9\u6837\u5566\uff0c\u611f\u5174\u8da3\u7684\u8bdd\u53bb\u5b98\u65b9\u9875\u9762\u770b\u770b\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/cli-weather-client\/","summary":"<p><a href=\"https:\/\/github.com\/chubin\/wttr.in\" target=\"_blank\">chubin\/wttr.in<\/a> \u662f\u4e00\u6b3e\u9762\u5411\u547d\u4ee4\u884c\u7684\u5929\u6c14\u9884\u62a5\u670d\u52a1\uff0c\u652f\u6301\u591a\u79cd HTTP \u5ba2\u6237\u7aef\u8fdb\u884c\u8bf7\u6c42\uff0c\u4f8b\u5982\uff1a<code>curl<\/code> \/ <code>httpie<\/code> \/ <code>wget<\/code> \u7b49\u3002\u8be5\u9879\u76ee\u7684\u5b98\u65b9\u63cf\u8ff0\u4fbf\u662f\uff1a<\/p>\n<blockquote>\n<p>The right way to check the weather.<\/p>\n<\/blockquote>","title":"\u547d\u4ee4\u884c\u67e5\u8be2\u5929\u6c14\u7684\u6b63\u786e\u65b9\u5f0f"},{"content":"\u5728 Windows \u4e0b\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 WinHex\uff0c\u800c\u5728 macOS \u5e73\u53f0\u4e0a\uff0c\u6709\u4ec0\u4e48\u4e0d\u9519\u7684\u5341\u516d\u8fdb\u5236\u67e5\u770b\u5668\u3001\u7f16\u8f91\u5668\u5462\uff1f\n\u51c6\u5907 \u9996\u5148\uff0c\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u6587\u4ef6\u7528\u4e8e\u6d4b\u8bd5\u3002\necho &#39;welcome&#39; &gt; file1 \u6b63\u6587 HexDump \u5f88\u591a\u7c7b Unix \u7cfb\u7edf\u90fd\u5305\u542b\u8fd9\u4e2a\u5de5\u5177\u3002\u6b63\u5982\u5176\u540d\uff0c\u529f\u80fd\u5c31\u662f\u5bfc\u51fa\u6587\u4ef6\u7684\u539f\u59cb\u5341\u516d\u8fdb\u5236\u4fe1\u606f\u3002\n$ hexdump file1 0000000 6577 636c 6d6f 0a65 0000008 \u4ee5\u4e0a\u8f93\u51fa\u5c31\u662f welcome \u7684 ASCII \u5341\u516d\u8fdb\u5236\u4fe1\u606f\uff0c\u5982\u679c\u6587\u4ef6\u5f88\u957f\uff0c\u90a3\u5c06\u4f1a\u5f88\u96be\u4e0e\u6587\u672c\u4fe1\u606f\u5bf9\u5e94\u8d77\u6765\u3002\n\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 -C \u9009\u9879\u6765\u540c\u65f6\u6253\u5370\u6587\u672c\u3002\n$ hexdump -C file1 00000000 77 65 6c 63 6f 6d 65 0a |welcome.| 00000008 \u5982\u4e0a\uff0cw \u7684\u5341\u516d\u8fdb\u5236 ASCII \u7801\u4e3a 77\uff0ce \u4e3a 65\u3002\nod \u53e6\u4e00\u4e2a\u5341\u5206\u5e38\u7528\u7684\u5de5\u5177\u662f od\u3002\u8be5\u5de5\u5177\u63d0\u4f9b -x \u53c2\u6570\u7528\u4e8e\u8f93\u51fa\u5341\u516d\u8fdb\u5236\u7684\u6587\u4ef6\u539f\u59cb\u6570\u636e\u3002\n$ od -x file1 0000000 6577 636c 6d6f 0a65 0000010 \u540c\u6837\uff0c\u4e3a\u4e86\u8ba9\u8f93\u51fa\u66f4\u52a0\u6613\u8bfb\uff0c\u53ef\u4f7f\u7528 -c \u53c2\u6570\u8f93\u51fa\u6587\u672c\u3002\n$ od -xc file1 0000000 6577 636c 6d6f 0a65 w e l c o m e \\n 0000010 xxd xxd \u662f\u4e00\u4e2a\u7a0d\u7279\u6b8a\u7684\u5de5\u5177\uff0c\u5b83\u8fd8\u63d0\u4f9b\u4e86\u4e00\u4e2a -r \u9009\u9879\uff0c\u53ef\u5c06\u5341\u516d\u8fdb\u5236\u4fe1\u606f\u8f6c\u6362\u56de\u539f\u59cb\u6587\u4ef6\uff0c\u53ef\u7528\u4e8e\u7f16\u8f91 Hex \u5185\u5bb9\u3002\n$ xxd file1 0000000: 7765 6c63 6f6d 650a welcome. \u5047\u8bbe\u6211\u4eec\u6709 file2 \u6587\u4ef6\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a\n$ cat file2 000000: 7765 6c63 6f6d 650a \u90a3\u4e48\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 -r \u9009\u9879\u6765\u5c06\u5176\u8f6c\u6362\u4e3a\u539f\u6587\u4ef6\u5185\u5bb9\uff1a\n$ xxd -r file2 welcome hexyl sharkdp\/hexyl \u662f\u4e00\u6b3e\u4f7f\u7528 Rust \u7f16\u5199\u7684 Hex \u67e5\u770b\u5668\uff0c\u652f\u6301\u9ad8\u4eae\u4e0d\u540c\u79cd\u7c7b\u7684\u5b57\u8282\u3002\n\u5b83\u5e76\u4e0d\u5e38\u89c1\uff0c\u662f\u6211\u6700\u8fd1\u5728 GitHub \u4e0a\u53d1\u73b0\u7684\u4e00\u4e2a\u5c0f\u5de5\u5177\uff0c\u524d\u4e9b\u5929\u4e0a\u5230 Trending \u72c2\u63fd 1k+ Stars\u3002\n$ hexyl file1 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250200000000\u2502 77 65 6c 63 6f 6d 65 0a \u250a \u2502welcome_\u250a \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u5b83\u8fd8\u652f\u6301\u4f7f\u7528 -n &lt;N&gt; \u9009\u9879\u6765\u9650\u5236\u4ec5\u8bfb\u53d6\u6587\u4ef6\u7684\u524d &lt;N&gt; \u4e2a\u5b57\u8282\u3002\n$ hexyl -n 2 file1 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250200000000\u2502 77 65 \u250a \u2502we \u250a \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 Vim Vim \u53ef\u8c13\u662f\u7f16\u8f91\u5668\u754c\u7684\u300c\u91cd\u91cf\u7ea7\u6b66\u5668\u300d\u4e86\u3002\u4e0a\u6587\u6211\u4eec\u4ecb\u7ecd\u7684\u90fd\u662f Hex \u67e5\u770b\u5668\uff0c\u4e0d\u4ec5\u5982\u6b64\uff0cVim \u8fd8\u63d0\u4f9b\u4e86\u76f4\u63a5\u7684\u7f16\u8f91\u529f\u80fd\u3002\n\u4f7f\u7528 Vim \u6253\u5f00\u6587\u4ef6\u540e\uff0c\u8f93\u5165 :% ! xxd \u547d\u4ee4\uff0c\u754c\u9762\u5c06\u53d8\u6210\u7c7b\u4f3c\u5982\u4e0b\u683c\u5f0f\uff1a\n00000000: 7765 6c63 6f6d 650a welcome. \u63a5\u7740\u4f60\u53ef\u4ee5\u968f\u610f\u7f16\u8f91\u6587\u672c\u4e86\uff0c\u5c31\u50cf\u4f7f\u7528 xxd \u8f6c\u6362\u540e\u8fdb\u884c\u7f16\u8f91\u4fee\u6539\u4e00\u6837\u3002\n\u5b8c\u6210\u540e\uff0c\u8f93\u5165 :%!xxd -r \u547d\u4ee4\u5e76\u4fdd\u5b58\u5373\u53ef\u3002\n\u53c2\u8003\u8d44\u6599  http:\/\/www.theunixschool.com\/2011\/06\/3-different-ways-of-dumping-hex.html https:\/\/stackoverflow.com\/questions\/827326\/whats-a-good-hex-editor-viewer-for-the-mac ","permalink":"https:\/\/wi1dcard.dev\/posts\/hex-viewers-and-editors-in-terminal\/","summary":"<p>\u5728 Windows \u4e0b\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 WinHex\uff0c\u800c\u5728 macOS \u5e73\u53f0\u4e0a\uff0c\u6709\u4ec0\u4e48\u4e0d\u9519\u7684\u5341\u516d\u8fdb\u5236\u67e5\u770b\u5668\u3001\u7f16\u8f91\u5668\u5462\uff1f<\/p>","title":"macOS \u7ec8\u7aef\u53ef\u7528\u7684 Hex \u67e5\u770b\u4e0e\u7f16\u8f91\u5668"},{"content":"jdorn\/sql-formatter \u662f\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684 PHP \u7c7b\u7528\u4e8e\u683c\u5f0f\u5316 SQL \u8bed\u53e5\u3002\n\u5b83\u652f\u6301\u81ea\u52a8\u8fdb\u884c\u7f29\u8fdb\u3001\u6dfb\u52a0\u6362\u884c\uff0c\u751a\u81f3\u8fd8\u652f\u6301\u8bed\u6cd5\u9ad8\u4eae\u3002\n\u5728\u547d\u4ee4\u884c\u5185\u4f7f\u7528 \u8be5\u6269\u5c55\u5305\u5305\u542b\u4e00\u4e2a bin\/sql-formatter \u53ef\u6267\u884c\u6587\u4ef6\uff0c\u53ef\u76f4\u63a5\u7528\u4e8e\u547d\u4ee4\u884c\u683c\u5f0f\u5316 SQL\u3002\n\u4f7f\u7528 Composer \u5168\u5c40\u5b89\u88c5\u540e\u4fbf\u53ef\u4f7f\u7528\u8be5\u547d\u4ee4\u4e86\uff1a\ncomposer global require jdorn\/sql-formatter sql-formatter &#34;SELECT SOME QUERY;&#34; \/\/ \u76f4\u63a5\u683c\u5f0f\u5316 \/\/ \u6216 echo &#34;SELECT SOME QUERY;&#34; | sql-formatter \/\/ \u4f7f\u7528\u7ba1\u9053\uff0c\u66f4\u9002\u5408\u8f83\u5927\u91cf\u7684 SQL \u8bed\u53e5 \u4f5c\u4e3a\u6269\u5c55\u5305\u4f7f\u7528 SqlFormatter \u7c7b\u5305\u542b\u4e00\u4e2a\u540d\u4e3a format \u7684\u9759\u6001\u65b9\u6cd5\uff0c\u5b83\u53ef\u4ee5\u63a5\u6536\u4e00\u4e2a SQL \u8bed\u53e5\u5b57\u7b26\u4e32\u4f5c\u4e3a\u53c2\u6570\uff0c\u5e76\u8fd4\u56de\u683c\u5f0f\u5316\u540e\u4f7f\u7528 pre \u6807\u7b7e\u5305\u88f9\u7684 HTML \u4ee3\u7801\u3002\n\u4f8b\u5982\uff1a\n&lt;?php require_once(&#39;SqlFormatter.php&#39;); $query = &#34;SELECT count(*),`Column1`,`Testing`, `Testing Three` FROM `Table1` WHERE Column1 = &#39;testing&#39; AND ( (`Column2` = `Column3` OR Column4 &gt;= NOW()) ) GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10&#34;; echo SqlFormatter::format($query); \u8f93\u51fa\uff1a\n\u53ea\u683c\u5f0f\u5316\u4e0d\u9ad8\u4eae \u82e5\u662f\u4e0d\u9700\u8981\u9ad8\u4eae\uff0c\u53ea\u9700\u8981\u6dfb\u52a0\u7f29\u8fdb\u548c\u6362\u884c\uff0c\u8bf7\u5c06\u7b2c\u4e8c\u4e2a\u53c2\u6570\u8bbe\u7f6e\u4e3a false \u5373\u53ef\u3002\n\u9002\u7528\u4e8e\u8f93\u51fa\u9519\u8bef\u65e5\u5fd7\u6216\u8005\u5176\u5b83\u975e HTML \u6570\u636e\u65f6\u3002\n&lt;?php echo SqlFormatter::format($query, false); \u8f93\u51fa\uff1a\n\u53ea\u9ad8\u4eae\u4e0d\u683c\u5f0f\u5316 \u6709\u4e2a\u5355\u72ec\u7684\u65b9\u6cd5\u540d\u4e3a highlight \u80fd\u591f\u4fdd\u8bc1\u539f\u6709\u7684\u683c\u5f0f\u4e0d\u88ab\u6539\u52a8\uff0c\u53ea\u6dfb\u52a0\u8bed\u6cd5\u9ad8\u4eae\u3002\n\u9002\u7528\u4e8e SQL \u5df2\u7ecf\u88ab\u826f\u597d\u683c\u5f0f\u5316\uff0c\u9700\u8ba9\u5b83\u66f4\u52a0\u6613\u8bfb\u65f6\u3002\n\u538b\u7f29\u67e5\u8be2\u8bed\u53e5 compress \u65b9\u6cd5\u53ef\u5220\u9664\u6240\u6709\u7684 SQL \u6ce8\u91ca\uff0c\u5e76\u538b\u7f29\u4e0d\u5fc5\u8981\u7684\u7a7a\u683c\u3002\n\u9002\u7528\u4e8e\u8f93\u51fa\u591a\u6761\u67e5\u8be2\u8bed\u53e5\uff0c\u5e76\u4f7f\u5176\u6613\u4e8e\u590d\u5236\u7c98\u8d34\u5230\u547d\u4ee4\u884c\u65f6\u3002\n-- This is a comment SELECT \/* This is another comment On more than one line *\/ Id #This is one final comment as temp, DateCreated as Created FROM MyTable; echo SqlFormatter::compress($query); \u8f93\u51fa\uff1a\nSELECT Id as temp, DateCreated as Created FROM MyTable; \u5220\u9664\u6ce8\u91ca \u5982\u679c\u4f60\u9700\u8981\u4fdd\u7559\u539f\u6709\u683c\u5f0f\uff0c\u4f46\u4ecd\u9700\u5220\u9664 SQL \u6ce8\u91ca\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 removeComments \u65b9\u6cd5\u6765\u4ee3\u66ff compress\u3002\n-- This is a comment SELECT \/* This is another comment On more than one line *\/ Id #This is one final comment as temp, DateCreated as Created FROM MyTable; echo SqlFormatter::removeComments($query); \u8f93\u51fa\uff1a\n SELECT Id as temp, DateCreated as Created FROM MyTable; \u5c06\u591a\u6761 SQL \u8bed\u53e5\u5206\u5272\u4e3a\u6570\u7ec4 \u8fd8\u6709\u4e00\u4e2a\u4e0e\u683c\u5f0f\u5316\u65e0\u5173\u7684\u7279\u6027\uff0c\u80fd\u591f\u5c06\u591a\u6761 SQL \u8bed\u53e5\u5206\u79bb\u4e3a\u6570\u7ec4\u3002\n\u4f8b\u5982\uff1a\nDROP TABLE IF EXISTS MyTable; CREATE TABLE MyTable ( id int ); INSERT INTO MyTable\t(id) VALUES (1),(2),(3),(4); SELECT * FROM MyTable; $queries = SqlFormatter::splitQuery($sql); \u7ed3\u679c\uff1a\n DROP TABLE IF EXISTS MyTable; CREATE TABLE MyTable ( id int ); INSERT INTO MyTable (id) VALUES (1),(2),(3),(4); SELECT * FROM MyTable;  \u4e3a\u4f55\u4e0d\u4f7f\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\uff1f \u53bb\u770b\u770b README \u5427\uff5ehttps:\/\/github.com\/jdorn\/sql-formatter#why-not-regular-expressions\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/format-sql-statements-in-php\/","summary":"<p><a href=\"https:\/\/github.com\/jdorn\/sql-formatter\" target=\"_blank\">jdorn\/sql-formatter<\/a> \u662f\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684 PHP \u7c7b\u7528\u4e8e\u683c\u5f0f\u5316 SQL \u8bed\u53e5\u3002<\/p>\n<p>\u5b83\u652f\u6301\u81ea\u52a8\u8fdb\u884c\u7f29\u8fdb\u3001\u6dfb\u52a0\u6362\u884c\uff0c\u751a\u81f3\u8fd8\u652f\u6301\u8bed\u6cd5\u9ad8\u4eae\u3002<\/p>","title":"\u5728 PHP \u4e2d\u683c\u5f0f\u5316\u5e76\u9ad8\u4eae SQL \u8bed\u53e5"},{"content":"\u4eca\u5929\u7ed9\u535a\u5ba2\u6587\u7ae0\u6574\u7406\u5206\u7c7b\uff0c\u5c06\u5168\u5c0f\u5199\u6539\u4e3a\u5355\u8bcd\u5927\u5199\u5f00\u5934\u7684\u8fc7\u7a0b\u4e2d\uff0c\u5076\u7136\u53d1\u73b0\u81ea\u5df1\u5df2\u7ecf\u8fbe\u6210 100 \u7bc7\u535a\u6587\u7684\u6210\u5c31\uff0c\u5c0f\u5c0f\u7684\u5e86\u795d\u4e00\u4e0b\u5427\u3002\n\u53e6\u5916\u63a5\u4e0b\u6765\u8981\u5f00\u65b0\u5751\u4e86\uff0c\u773c\u770b\u7740\u81ea\u5df1\u6df1\u5ea6\u4f7f\u7528 GitHub \u4e5f\u6709\u4e00\u9635\u5b50\u4e86\uff0cStar \u7684\u4ed3\u5e93\u6570\u91cf\u5373\u5c06\u7a81\u7834 500\u3002\u51e0\u5929\u524d\u6574\u7406\u53c8\u6574\u7406\u3001\u7b5b\u9009\u53c8\u7b5b\u9009\uff0c\u7cbe\u9009\u4e86\u90e8\u5206\u4e0d\u9519\u7684\u9879\u76ee\uff0c\u53ef\u80fd\u5f88\u5c0f\u4f17\uff0c\u53ef\u80fd\u5f88\u7b80\u5355\uff0c\u4e0e\u5176\u7559\u5728 Stared list \u91cc\u5403\u7070\uff0c\u4e0d\u5982\u548c\u5927\u5bb6\u5206\u4eab\u4e00\u4e0b\uff0c\u6b63\u6240\u8c13\u72ec\u4e50\u4e50\u4e0d\u5982\u4f17\u4e50\u4e50\u3002\n\u63a5\u4e0b\u6765\u5c06\u66f4\u65b0\u4e00\u7cfb\u5217\u7684\u6587\u7ae0\uff0c\u4ece GitHub \u6458\u9009\u4e00\u4e9b\u6211\u8ba4\u4e3a\u4e0d\u9519\u7684 \u4e2d\u5c0f\u578b \u5f00\u6e90\u9879\u76ee\uff0c\u5e0c\u671b\u80fd\u591f \u5feb\u901f \u7ed9\u4e88\u4f60\u4e00\u4e9b\u7075\u611f\u3001\u542f\u53d1\u548c\u5e2e\u52a9\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/100-posts\/","summary":"\u4eca\u5929\u7ed9\u535a\u5ba2\u6587\u7ae0\u6574\u7406\u5206\u7c7b\uff0c\u5c06\u5168\u5c0f\u5199\u6539\u4e3a\u5355\u8bcd\u5927\u5199\u5f00\u5934\u7684\u8fc7\u7a0b\u4e2d\uff0c\u5076\u7136\u53d1\u73b0\u81ea\u5df1\u5df2\u7ecf\u8fbe\u6210 100 \u7bc7\u535a\u6587\u7684\u6210\u5c31\uff0c\u5c0f\u5c0f\u7684\u5e86\u795d\u4e00\u4e0b\u5427\u3002\n\u53e6\u5916\u63a5\u4e0b\u6765\u8981\u5f00\u65b0\u5751\u4e86\uff0c\u773c\u770b\u7740\u81ea\u5df1\u6df1\u5ea6\u4f7f\u7528 GitHub \u4e5f\u6709\u4e00\u9635\u5b50\u4e86\uff0cStar \u7684\u4ed3\u5e93\u6570\u91cf\u5373\u5c06\u7a81\u7834 500\u3002\u51e0\u5929\u524d\u6574\u7406\u53c8\u6574\u7406\u3001\u7b5b\u9009\u53c8\u7b5b\u9009\uff0c\u7cbe\u9009\u4e86\u90e8\u5206\u4e0d\u9519\u7684\u9879\u76ee\uff0c\u53ef\u80fd\u5f88\u5c0f\u4f17\uff0c\u53ef\u80fd\u5f88\u7b80\u5355\uff0c\u4e0e\u5176\u7559\u5728 Stared list \u91cc\u5403\u7070\uff0c\u4e0d\u5982\u548c\u5927\u5bb6\u5206\u4eab\u4e00\u4e0b\uff0c\u6b63\u6240\u8c13\u72ec\u4e50\u4e50\u4e0d\u5982\u4f17\u4e50\u4e50\u3002\n\u63a5\u4e0b\u6765\u5c06\u66f4\u65b0\u4e00\u7cfb\u5217\u7684\u6587\u7ae0\uff0c\u4ece GitHub \u6458\u9009\u4e00\u4e9b\u6211\u8ba4\u4e3a\u4e0d\u9519\u7684 \u4e2d\u5c0f\u578b \u5f00\u6e90\u9879\u76ee\uff0c\u5e0c\u671b\u80fd\u591f \u5feb\u901f \u7ed9\u4e88\u4f60\u4e00\u4e9b\u7075\u611f\u3001\u542f\u53d1\u548c\u5e2e\u52a9\u3002","title":"\u6210\u529f\u8fbe\u6210\u6210\u5c31 \u2014\u2014 100 \u7bc7\u535a\u6587"},{"content":" \u8bd1\u8005\u5e8f\uff1aPrometheus \u662f\u670d\u52a1\u5668\u76d1\u63a7\u7cfb\u7edf\u7684\u540e\u8d77\u4e4b\u79c0\uff0c\u53ef\u4ee5\u548c Kubernetes \u5b8c\u7f8e\u7ed3\u5408\u7528\u4e8e\u76d1\u63a7\u5927\u91cf\u96c6\u7fa4\u548c\u5e94\u7528\u3002Grafana \u662f\u4e00\u6b3e\u6570\u636e\u53ef\u89c6\u5316\u770b\u677f\uff0c\u53ef\u6307\u5b9a\u591a\u4e2a\u6570\u636e\u6e90\u6267\u884c\u67e5\u8be2\uff0c\u5c06\u67af\u71e5\u7684\u6570\u636e\u8f6c\u5316\u4e3a\u591a\u7ef4\u5ea6\u7684\u9762\u677f\u3002\u4e24\u8005\u5747\u4e3a\u5f00\u6e90\u9879\u76ee\uff0c\u901a\u8fc7\u914d\u7f6e\u53ef\u5b9e\u73b0\u76f4\u89c2\u5f3a\u5927\u7684\u76d1\u63a7\u3001\u62a5\u8b66\u3001\u5206\u6790\u7cfb\u7edf\uff0c\u5b9e\u5c5e\u8fd0\u7ef4\u795e\u5668\u3002\n \u6548\u679c\u9884\u89c8\uff1a\n \u539f\u6587\u5730\u5740\uff1ahttps:\/\/www.scaleway.com\/docs\/configure-prometheus-monitoring-with-grafana\/\n \u672c\u6587\u5c06\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Prometheus + Grafana \u770b\u677f\u76d1\u63a7\u670d\u52a1\u5668\u72b6\u6001\u3002\nPrometheus\uff08\u666e\u7f57\u7c73\u4fee\u65af\uff09\u662f\u4e00\u6b3e\u4ece 2012 \u5e74\u5f00\u59cb\u7814\u53d1\u7684\u5f39\u6027\u76d1\u63a7\u89e3\u51b3\u65b9\u6848\u3002\u8be5\u7cfb\u7edf\u5c06\u5176\u6570\u636e\u5b58\u50a8\u81f3\u65f6\u5e8f\u6570\u636e\u5e93\uff0c\u4e14\u63d0\u4f9b\u4e86\u591a\u7ef4\u5ea6\u7684\u6570\u636e\u6a21\u578b\u548c\u5f3a\u5927\u7684\u67e5\u8be2\u8bed\u8a00\u6765\u751f\u6210\u88ab\u76d1\u63a7\u8d44\u6e90\u7684\u62a5\u8868\u3002\n\u8981\u4f7f\u7528 Prometheus \u548c Grafana \u5927\u7ea6\u6709\u4e94\u4e2a\u6b65\u9aa4\uff1a\n \u51c6\u5907\u670d\u52a1\u5668\u73af\u5883 \u4e0b\u8f7d\u5e76\u5b89\u88c5 Node Exporter \u4e0b\u8f7d\u5e76\u5b89\u88c5 Prometheus \u914d\u7f6e Prometheus \u4e0b\u8f7d\u5e76\u5b89\u88c5 Grafana  \u51c6\u5907\u670d\u52a1\u5668\u73af\u5883 \u5728\u672c\u6559\u7a0b\u5185\uff0c\u6211\u4eec\u4f7f\u7528 Ubuntu Xenial\uff0816.04\uff09\u7cfb\u7edf\u6765\u6f14\u793a\u3002\n  \u4e3a\u4e86\u80fd\u591f\u8ba9 Prometheus \u5b89\u5168\u5730\u8fd0\u884c\u5728\u6211\u4eec\u7684\u670d\u52a1\u5668\u4e0a\uff0c\u6211\u4eec\u9996\u5148\u8981\u4e3a Prometheus \u548c Node Exporter \u521b\u5efa\u4e00\u4e2a\u4e0d\u542b\u767b\u5f55\u6743\u9650\u7684\u7528\u6237\u3002\u53ef\u4f7f\u7528 --no-create-home \u53c2\u6570\u907f\u514d\u521b\u5efa\u7528\u6237\u6839\u76ee\u5f55\uff0c\u4f7f\u7528 --shell \/usr\/sbin\/nologin \u6765\u7981\u6b62\u7528\u6237\u6253\u5f00 Shell\u3002\nsudo useradd --no-create-home --shell \/usr\/sbin\/nologin prometheus sudo useradd --no-create-home --shell \/bin\/false node_exporter   \u521b\u5efa\u76ee\u5f55\uff0c\u7528\u4e8e\u5b58\u50a8 Prometheus \u53ef\u6267\u884c\u6587\u4ef6\u4ee5\u53ca\u5176\u914d\u7f6e\uff1a\nsudo mkdir \/etc\/prometheus sudo mkdir \/var\/lib\/prometheus   \u8bbe\u7f6e\u4ee5\u4e0a\u76ee\u5f55\u7684\u62e5\u6709\u8005\u4e3a prometheus \u7528\u6237\uff0c\u786e\u4fdd Prometheus \u6709\u6743\u9650\u8bbf\u95ee\u8fd9\u4e9b\u6587\u4ef6\u5939\u3002\nsudo chown prometheus:prometheus \/etc\/prometheus sudo chown prometheus:prometheus \/var\/lib\/prometheus   \u4e0b\u8f7d\u5e76\u5b89\u88c5 Node Exporter \u7531\u4e8e Prometheus \u4ec5\u5177\u5907\u91c7\u96c6\u7cfb\u7edf\u6307\u6807\u7684\u529f\u80fd\uff0c\u56e0\u6b64\u6211\u4eec\u9700\u8981\u901a\u8fc7 Node Exporter \u6765\u6269\u5c55\u5b83\u7684\u80fd\u529b\u3002Node Exporter \u662f\u4e00\u6b3e\u6536\u96c6\u7cfb\u7edf CPU\u3001\u78c1\u76d8\u3001\u5185\u5b58\u7528\u91cf\u4fe1\u606f\u5e76\u5c06\u5b83\u4eec\u516c\u5f00\u4ee5\u4f9b\u6293\u53d6\u7684\u5de5\u5177\u3002\n  \u4e0b\u8f7d Node Exporter \u7684\u6700\u65b0\u7248\u672c\u3002\nwget https:\/\/github.com\/prometheus\/node_exporter\/releases\/download\/v0.16.0\/node_exporter-0.16.0.linux-amd64.tar.gz  \u8bd1\u8005\u6ce8\uff1a\u7531\u4e8e\u672c\u6587\u9879\u76ee\u4ecd\u5728\u6301\u7eed\u66f4\u65b0\uff0c\u6545\u8bf7\u5230 GitHub \u67e5\u770b\u6700\u65b0\u7248\u672c Release \u94fe\u63a5\u518d\u4e0b\u8f7d\u3002\u4ee5\u4e0b\u7c7b\u540c\uff0c\u4e0d\u518d\u8d58\u8ff0\u3002\n   \u89e3\u538b\u538b\u7f29\u5305\u540e\uff0c\u4f1a\u53d1\u73b0\u4e00\u4e2a\u540d\u4e3a node_exporter-0.16.0.linux-amd64 \u7684\u76ee\u5f55\uff0c\u5305\u542b\u4e86\u53ef\u6267\u884c\u6587\u4ef6\u3001README \u4ee5\u53ca\u8bb8\u53ef\u8bc1\u6587\u4ef6\uff1a\ntar xvf node_exporter-0.16.0.linux-amd64.tar.gz   \u590d\u5236\u5176\u4e2d\u7684\u53ef\u6267\u884c\u6587\u4ef6\u5230 \/usr\/local\/bin \u76ee\u5f55\u4e0b\uff0c\u5e76\u5c06\u5176\u62e5\u6709\u8005\u8bbe\u4e3a\u4e0a\u6587\u521b\u5efa\u7684 node_exporter \u7528\u6237\uff1a\nsudo cp node_exporter-0.16.0.linux-amd64\/node_exporter \/usr\/local\/bin sudo chown node_exporter:node_exporter \/usr\/local\/bin\/node_exporter   Node Exporter \u5269\u4f59\u7684\u6587\u4ef6\u5df2\u4e0d\u9700\u8981\uff0c\u5220\u9664\u5373\u53ef\uff1a\nrm -rf node_exporter-0.16.0.linux-amd64.tar.gz node_exporter-0.16.0.linux-amd64   \u4e3a\u4e86\u8ba9 Node Exporter \u80fd\u591f\u8ddf\u968f\u7cfb\u7edf\u81ea\u52a8\u542f\u52a8\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa\u4e00\u4e2a Systemd \u670d\u52a1\u3002\u4f8b\u5982\u4f7f\u7528 Nano \u7f16\u8f91\u5668\u521b\u5efa\u8be5\u670d\u52a1\u6587\u4ef6\uff1a\nsudo nano \/etc\/systemd\/system\/node_exporter.service   \u5c06\u4ee5\u4e0b\u5185\u5bb9\u590d\u5236\u5230\u6587\u4ef6\u5185\uff0c\u4fdd\u5b58\u5e76\u9000\u51fa\u3002\n[Unit] Description=Node Exporter Wants=network-online.target After=network-online.target [Service] User=node_exporter Group=node_exporter Type=simple ExecStart=\/usr\/local\/bin\/node_exporter [Install] WantedBy=multi-user.target   \u5728 Node Exporter \u4e2d\uff0c\u6536\u96c6\u5668\uff08Collectors\uff09\u7528\u4e8e\u641c\u96c6\u7cfb\u7edf\u4fe1\u606f\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e00\u90e8\u5206\u6536\u96c6\u5668\u5df2\u88ab\u5f00\u542f\uff0c\u4f60\u53ef\u4ee5\u5728 README \u6587\u4ef6\u4e2d\u67e5\u770b\u5177\u4f53\u5217\u8868\u3002\u5982\u679c\u4f60\u60f3\u8981\u4f7f\u7528\u67d0\u4e9b\u7279\u5b9a\u7684\u6536\u96c6\u5668\uff0c\u53ef\u4ee5\u5728\u4ee5\u4e0a\u6587\u4ef6\u7684 ExecStart \u914d\u7f6e\u4e2d\u8fdb\u884c\u5b9a\u4e49\u3002\u4f8b\u5982\uff1a\nExecStart=\/usr\/local\/bin\/node_exporter --collectors.enabled meminfo,hwmon,entropy \u7f16\u8f91\u540e\u8bb0\u5f97\u4fdd\u5b58\u3002\n  \u91cd\u542f Systemd \u4ee5\u4fbf\u80fd\u591f\u4f7f\u7528\u65b0\u521b\u5efa\u7684\u670d\u52a1\uff1a\nsudo systemctl daemon-reload   \u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8 Node Exporter\uff1a\nsudo systemctl start node_exporter   \u786e\u4fdd\u5176\u542f\u52a8\u6210\u529f\uff1a\nsudo systemctl status node_exporter \u4f60\u5c06\u4f1a\u770b\u5230\u7c7b\u4f3c\u5982\u4e0b\u7684\u8f93\u51fa\uff0c\u5206\u522b\u5c55\u793a\u5df2\u542f\u52a8\u72b6\u6001 active (running)\uff0c\u4ee5\u53ca\u4e3b\u8fdb\u7a0b ID\uff08PID\uff09\uff1a\n\u25cf node_exporter.service - Node Exporter Loaded: loaded (\/etc\/systemd\/system\/node_exporter.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2018-06-25 11:47:06 UTC; 4s ago Main PID: 1719 (node_exporter) CGroup: \/system.slice\/node_exporter.service \u2514\u25001719 \/usr\/local\/bin\/node_exporter   \u6ca1\u4ec0\u4e48\u95ee\u9898\u7684\u8bdd\uff0c\u4fbf\u53ef\u4ee5\u5f00\u542f Node Exporter \u7684\u5f00\u673a\u81ea\u542f\u52a8\u4e86\uff1a\nsudo systemctl enable node_exporter   \u4e0b\u8f7d\u5e76\u5b89\u88c5 Prometheus   \u4e0b\u8f7d\u5e76\u89e3\u538b Prometheus \u7684\u6700\u65b0\u7248\u672c\u3002\nsudo apt-get update &amp;&amp; apt-get upgrade wget https:\/\/github.com\/prometheus\/prometheus\/releases\/download\/v2.2.1\/prometheus-2.2.1.linux-amd64.tar.gz tar xfz prometheus-*.tar.gz cd prometheus-* \u8be5\u76ee\u5f55\u5185\u5305\u542b\u4ee5\u4e0b\u4e24\u4e2a\u53ef\u6267\u884c\u6587\u4ef6\uff1a - prometheus - Prometheus \u4e3b\u7a0b\u5e8f - promtool\n\u4ee5\u4e0b\u4e24\u4e2a\u5b50\u76ee\u5f55\u5219\u5206\u522b\u5305\u542b\u4e86 Web \u63a5\u53e3\u3001\u793a\u4f8b\u914d\u7f6e\u4ee5\u53ca\u8bb8\u53ef\u8bc1\u6587\u4ef6\uff1a - console - console_libraries\n  \u590d\u5236\u53ef\u6267\u884c\u6587\u4ef6\u5230 \/usr\/local\/bin\/ \u76ee\u5f55\u3002\nsudo cp .\/prometheus \/usr\/local\/bin\/ sudo cp .\/promtool \/usr\/local\/bin\/   \u8bbe\u7f6e\u4ee5\u4e0a\u6587\u4ef6\u7684\u62e5\u6709\u8005\u4e3a\u4e0a\u6587\u521b\u5efa\u7684 prometheus \u7528\u6237\u3002\nsudo chown prometheus:prometheus \/usr\/local\/bin\/prometheus sudo chown prometheus:prometheus \/usr\/local\/bin\/promtool   \u590d\u5236 console \u548c console_libraries \u76ee\u5f55\u5230 \/etc\/prometheus\u3002\nsudo cp -r .\/consoles \/etc\/prometheus sudo cp -r .\/console_libraries \/etc\/prometheus   \u8bbe\u7f6e\u4ee5\u4e0a\u76ee\u5f55\u53ca\u5176\u5b50\u76ee\u5f55\u548c\u6587\u4ef6\u7684\u62e5\u6709\u8005\u4e3a prometheus \u7528\u6237\u3002\nsudo chown -R prometheus:prometheus \/etc\/prometheus\/consoles sudo chown -R prometheus:prometheus \/etc\/prometheus\/console_libraries   \u56de\u5230\u5148\u524d\u4e0b\u8f7d\u7684\u76ee\u5f55\uff0c\u5220\u9664\u4e0d\u518d\u9700\u8981\u7684\u539f\u59cb\u6587\u4ef6\u3002\ncd .. &amp;&amp; rm -rf prometheus-*   \u914d\u7f6e Prometheus \u5728\u4f7f\u7528 Prometheus \u4e4b\u524d\uff0c\u9996\u5148\u9700\u8981\u8fdb\u884c\u57fa\u672c\u7684\u914d\u7f6e\u3002\u7531\u6b64\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a prometheus.yml \u7684\u914d\u7f6e\u6587\u4ef6\u3002\n \u6ce8\u610f\uff1aPrometheus \u7684\u914d\u7f6e\u6587\u4ef6\u4f7f\u7528 YAML \u683c\u5f0f\uff0c\u4e25\u683c\u7981\u6b62\u4f7f\u7528 Tabs\u3002\u5982\u679c\u6587\u4ef6\u5185\u5bb9\u683c\u5f0f\u4e0d\u6b63\u786e\uff0cPrometheus \u5c06\u65e0\u6cd5\u6b63\u5e38\u542f\u52a8\u3002\u6545\u7f16\u8f91\u914d\u7f6e\u6587\u4ef6\u65f6\u8bf7\u7559\u5fc3\u3002\n   \u5728\u6587\u672c\u7f16\u8f91\u5668\uff08\u4f8b\u5982 Nano\uff09\u5185\u7f16\u8f91 prometheus.yml \u6587\u4ef6\u3002\nPrometheus \u7684\u914d\u7f6e\u6587\u4ef6\u5206\u4e3a\u4e09\u4e2a\u90e8\u5206\uff1aglobal\u3001rule_files \u548c scrape_configs\u3002\n\u5728 global \u90e8\u5206\u5185\uff0c\u53ef\u4ee5\u627e\u5230\u4e00\u4e9b\u901a\u7528\u914d\u7f6e\uff1ascrape_interval \u7528\u4e8e\u8bbe\u7f6e Prometheus \u591a\u4e45\u6293\u53d6\u4e00\u6b21\u76ee\u6807\uff08Targets\uff09\uff0cevaluation_interval \u7528\u4e8e\u8bbe\u7f6e\u591a\u4e45\u8ba1\u7b97\u4e00\u6b21\u89c4\u5219\uff08Rules\uff09\u3002\u800c\u89c4\u5219\u7528\u4e8e\u63a7\u5236\u5b58\u50a8\u9884\u5148\u8ba1\u7b97\u7684\u6570\u636e\uff0c\u4ee5\u53ca\u4f55\u65f6\u751f\u6210\u544a\u8b66\uff08Alert\uff09\u3002\n\u5728 rule_files \u90e8\u5206\u5185\uff0c\u5305\u542b\u4e86 Prometheus \u52a0\u8f7d\u7684\u89c4\u5219\u6587\u4ef6\u8def\u5f84\u3002\n\u914d\u7f6e\u6587\u4ef6\u7684\u6700\u540e\u4e00\u4e2a\u90e8\u5206\u540d\u4e3a scrape_configs\uff0c\u5305\u542b\u4e86 Prometheus \u76d1\u63a7\u7684\u8d44\u6e90\u4fe1\u606f\u3002\n\u4ee5\u4e0a\u914d\u7f6e\u6587\u4ef6\u770b\u8d77\u6765\u5e94\u5f53\u7c7b\u4f3c\uff1a\nglobal: scrape_interval: 15s evaluation_interval: 15s rule_files: # - &#34;first.rules&#34; # - &#34;second.rules&#34; scrape_configs: - job_name: &#39;prometheus&#39; scrape_interval: 5s static_configs: - targets: [&#39;localhost:9090&#39;] \u5168\u5c40 scrape_interval \u8bbe\u7f6e\u4e3a\u4e86\u9002\u7528\u4e8e\u591a\u6570\u60c5\u51b5\u7684 15 \u79d2\u3002\n\u6211\u4eec\u76ee\u524d\u8fd8\u6ca1\u6709\u4efb\u4f55\u89c4\u5219\u6587\u4ef6\uff0c\u6240\u4ee5 rule_files \u90e8\u5206\u5df2\u4f7f\u7528 # \u6ce8\u91ca\u3002\n\u5728 scrape_configs \u90e8\u5206\uff0c\u6211\u4eec\u5b9a\u4e49\u4e86\u7b2c\u4e00\u4e2a\u5bfc\u51fa\u5668\uff08Exporter\uff09\uff0c\u7528\u4e8e Prometheus \u76d1\u63a7\u5b83\u81ea\u5df1\u3002\u7531\u4e8e\u6211\u4eec\u9700\u8981\u66f4\u52a0\u7cbe\u786e\u7684 Prometheus \u72b6\u6001\u4fe1\u606f\uff0c\u6211\u4eec\u5c06\u8be5\u4efb\u52a1\uff08Job\uff09\u7684 scrape_interval \u964d\u4f4e\u4e3a 5 \u79d2\u3002static_configs \u7684 targets \u53c2\u6570\u8868\u793a\u5bfc\u51fa\u5668\u7684\u76d1\u542c\u5730\u5740\u3002\u5728\u672c\u4f8b\u4e2d\u662f\u540c\u4e00\u670d\u52a1\u5668\uff0c\u6240\u4ee5\u6211\u4eec\u4f7f\u7528 localhost \u4ee5\u53ca Prometheus \u81ea\u5df1\u7684\u7aef\u53e3 9090\u3002\nPrometheus \u5c06\u4f1a\u6293\u53d6\u5728 scrape_configs \u5185\u5b9a\u4e49\u7684\u5bfc\u51fa\u5668\uff0c\u56e0\u6b64\u6211\u4eec\u9700\u8981\u5c06 Node Exporter \u6dfb\u52a0\u81f3\u8be5\u6587\u4ef6\uff0c\u5c31\u50cf\u4e0a\u6587\u4e2d\u76d1\u63a7 Prometheus \u81ea\u5df1\u4e00\u6837\u3002\n\u5c06\u4ee5\u4e0b\u90e8\u5206\u52a0\u5165\u914d\u7f6e\u6587\u4ef6\u5373\u53ef\uff1a\n- job_name: &#39;node_exporter&#39; scrape_interval: 5s static_configs: - targets: [&#39;localhost:9100&#39;] \u5982\u4e0a\uff0c\u6211\u4eec\u518d\u6b21\u8986\u76d6\u4e86 scrape_interval \u914d\u7f6e\u5e76\u8bbe\u7f6e\u4e3a 5 \u79d2\u3002\u5e76\u4e14 Node Exporter \u4e0e Prometheus \u8fd0\u884c\u5728\u7edf\u4e00\u670d\u52a1\u5668\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528 localhost \u4ee5\u53ca Node Exporter \u7684\u9ed8\u8ba4\u7aef\u53e3\uff1a9100\u3002\n\u82e5\u662f\u4ece\u5916\u90e8\u670d\u52a1\u5668\u6293\u53d6\u6570\u636e\uff0c\u4f60\u9700\u8981\u4f7f\u7528\u8fdc\u7a0b\u670d\u52a1\u5668\u7684 IP \u5730\u5740\u66ff\u6362 localhost\u3002\n\u6b32\u77e5 Prometheus \u5168\u90e8\u914d\u7f6e\u9879\uff0c\u8bf7\u9605\u8bfb \u5b98\u65b9\u914d\u7f6e\u6587\u6863\u3002\n  \u8bbe\u7f6e\u8be5\u914d\u7f6e\u6587\u4ef6\u7684\u62e5\u6709\u8005\u4e3a prometheus \u7528\u6237\u3002\nsudo chown prometheus:prometheus \/etc\/prometheus\/prometheus.yml   \u597d\u4e86\uff0cPrometheus \u670d\u52a1\u5df2\u7ecf\u51c6\u5907\u597d\u5927\u663e\u8eab\u624b\u4e86\uff01\n\u8fd0\u884c Prometheus   \u76f4\u63a5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u542f\u52a8 Prometheus \u5373\u53ef\uff0c\u8be5\u547d\u4ee4\u5c06\u4f1a\u4ee5 prometheus \u7528\u6237\u7684\u8eab\u4efd\u8fd0\u884c\u3002\nsudo -u prometheus \/usr\/local\/bin\/prometheus --config.file \/etc\/prometheus\/prometheus.yml --storage.tsdb.path \/var\/lib\/prometheus\/ --web.console.templates=\/etc\/prometheus\/consoles --web.console.libraries=\/etc\/prometheus\/console_libraries \u63a5\u7740\uff0c\u4f60\u4f1a\u770b\u5230\u4e00\u4e9b\u72b6\u6001\u8f93\u51fa\uff0c\u4ee5\u53ca\u670d\u52a1\u5df2\u542f\u52a8\u7684\u4fe1\u606f\uff1a\nlevel=info ts=2018-04-12T11:56:53.084000977Z caller=main.go:220 msg=&quot;Starting Prometheus&quot; version=&quot;(version=2.2.1, branch=HEAD, revision=bc6058c81272a8d938c05e75607371284236aadc)&quot; level=info ts=2018-04-12T11:56:53.084463975Z caller=main.go:221 build_context=&quot;(go=go1.10, user=root@149e5b3f0829, date=20180314-14:15:45)&quot; level=info ts=2018-04-12T11:56:53.084632256Z caller=main.go:222 host_details=&quot;(Linux 4.4.127-mainline-rev1 #1 SMP Sun Apr 8 10:38:32 UTC 2018 x86_64 scw-041406 (none))&quot; level=info ts=2018-04-12T11:56:53.084797692Z caller=main.go:223 fd_limits=&quot;(soft=1024, hard=65536)&quot; level=info ts=2018-04-12T11:56:53.09190775Z caller=web.go:382 component=web msg=&quot;Start listening for connections&quot; address=0.0.0.0:9090 level=info ts=2018-04-12T11:56:53.091908126Z caller=main.go:504 msg=&quot;Starting TSDB ...&quot; level=info ts=2018-04-12T11:56:53.102833743Z caller=main.go:514 msg=&quot;TSDB started&quot; level=info ts=2018-04-12T11:56:53.103343144Z caller=main.go:588 msg=&quot;Loading configuration file&quot; filename=\/etc\/prometheus\/prometheus.yml level=info ts=2018-04-12T11:56:53.104047346Z caller=main.go:491 msg=&quot;Server is ready to receive web requests.&quot;   \u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u8f93\u5165 http:\/\/your.server.ip:9090 \u4fbf\u80fd\u591f\u8bbf\u95ee\u5230 Prometheus \u7684 Web \u9875\u9762\u4e86\u3002\u5982\u679c\u4e00\u5207\u6b63\u5e38\uff0c\u6211\u4eec\u9700\u8981\u5148\u6682\u65f6\u5728\u547d\u4ee4\u884c\u6309\u4e0b Ctrl + C \u7ed3\u675f\u8fdb\u7a0b\u3002\n \u5982\u679c\u542f\u52a8 Prometheus \u670d\u52a1\u65f6\u6709\u9519\u8bef\u4fe1\u606f\u8f93\u51fa\uff0c\u8bf7\u518d\u6b21\u786e\u8ba4\u914d\u7f6e\u6587\u4ef6\u662f\u5426\u5b58\u5728\u8bed\u6cd5\u9519\u8bef\u3002\u9519\u8bef\u4fe1\u606f\u5c06\u4f1a\u6307\u660e\u5e94\u5f53\u5982\u4f55\u68c0\u67e5\u3002\n   \u597d\u4e86\uff0cPrometheus \u5df2\u7ecf\u80fd\u591f\u6b63\u5e38\u5de5\u4f5c\uff0c\u4f46\u5b83\u8fd8\u6ca1\u6709\u8ddf\u968f\u7cfb\u7edf\u542f\u52a8\u3002\u63a5\u4e0b\u6765\u6211\u4eec\u518d\u6b21\u521b\u5efa\u4e00\u4e2a Systemd \u670d\u52a1\u6587\u4ef6\u6765\u544a\u77e5\u7cfb\u7edf\u5f00\u673a\u542f\u52a8\uff1a\nsudo nano \/etc\/systemd\/system\/prometheus.service \u8be5\u6587\u4ef6\u5c06\u4f1a\u6307\u660e\u4f7f\u7528 prometheus \u7528\u6237\u8fd0\u884c Prometheus\uff0c\u5e76\u6307\u5b9a\u5176\u914d\u7f6e\u6587\u4ef6\u7684\u8def\u5f84\u3002\n  \u590d\u5236\u4ee5\u4e0b\u5185\u5bb9\u5e76\u7c98\u8d34\uff0c\u4fdd\u5b58\u540e\u9000\u51fa\u6587\u672c\u7f16\u8f91\u5668\u3002\n[Unit] Description=Prometheus Monitoring Wants=network-online.target After=network-online.target [Service] User=prometheus Group=prometheus Type=simple ExecStart=\/usr\/local\/bin\/prometheus \\ --config.file \/etc\/prometheus\/prometheus.yml \\ --storage.tsdb.path \/var\/lib\/prometheus\/ \\ --web.console.templates=\/etc\/prometheus\/consoles \\ --web.console.libraries=\/etc\/prometheus\/console_libraries ExecReload=\/bin\/kill -HUP $MAINPID [Install] WantedBy=multi-user.target   \u91cd\u8f7d systemd \u540e\u624d\u80fd\u4f7f\u7528\u65b0\u521b\u5efa\u7684\u670d\u52a1\uff1a\nsudo systemctl daemon-reload \u5f00\u542f Prometheus \u670d\u52a1\uff0c\u5b9e\u73b0\u5f00\u673a\u81ea\u542f\uff1a\nsudo systemctl enable prometheus   \u542f\u52a8 Prometheus\uff1a\nsudo systemctl start prometheus   \u641e\u5b9a\uff0c\u6211\u4eec\u6210\u529f\u5b89\u88c5 Prometheus \u7528\u6765\u76d1\u63a7\u670d\u52a1\u5668\uff0cPrometheus \u670d\u52a1\u5df2\u7ecf\u53ef\u4ee5\u6b63\u5e38\u8bbf\u95ee\u4e86\u3002\nPrometheus Web \u7aef Prometheus \u5185\u7f6e\u4e00\u4e2a\u7b80\u6613\u7684 Web \u670d\u52a1\uff0c\u53ef\u901a\u8fc7 http:\/\/your.server.ip:9000 \u8bbf\u95ee\u3002\u901a\u8fc7\u5b83\u80fd\u591f\u67e5\u8be2\u5176\u6536\u96c6\u5230\u7684\u6570\u636e\u3002\n\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5b83\u9a8c\u8bc1 Prometheus \u670d\u52a1\u7684\u8fd0\u884c\u72b6\u6001\uff1a\n\u6b64\u5916\uff0c\u8fd8\u53ef\u4ee5\u67e5\u8be2\u88ab\u6536\u96c6\u7684\u6570\u636e\uff1a\n\u6b64 Web \u9875\u9762\u5341\u5206\u8f7b\u91cf\uff0c\u5982\u679c\u4f60\u4e0d\u4ec5\u4ec5\u53ea\u60f3\u6d4b\u8bd5\u4e00\u4e0b\u6548\u679c\uff0cPrometheus \u56e2\u961f\u5efa\u8bae\u4f7f\u7528\u7c7b\u4f3c Grafana \u7684\u5de5\u5177\u6765\u66ff\u4ee3\u5b83\u3002\n\u5b89\u88c5 Grafana   \u4e0b\u8f7d\u5e76\u5b89\u88c5 Grafana\u3002\nwget https:\/\/dl.grafana.com\/oss\/release\/grafana_5.4.2_amd64.deb sudo apt-get install -y adduser libfontconfig sudo dpkg -i grafana_5.4.2_amd64.deb   \u4f7f\u7528 systemd \u5f00\u542f Grafana \u7684\u5f00\u673a\u81ea\u542f\u52a8\u3002\nsudo systemctl daemon-reload &amp;&amp; sudo systemctl enable grafana-server &amp;&amp; sudo systemctl start grafana-server Grafana \u5df2\u7ecf\u5f00\u59cb\u8fd0\u884c\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 http:\/\/your.server.ip:3000 \u8bbf\u95ee\u3002\u9ed8\u8ba4\u7684\u7528\u6237\u540d\u548c\u5bc6\u7801\u662f admin \/ admin\u3002\n  \u73b0\u5728\u4f60\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u6570\u636e\u6e90\uff08Data Source\uff09\uff0c\u4e5f\u5c31\u662f Prometheus\uff1a\n \u70b9\u51fb Grafana Logo \u6253\u5f00\u4fa7\u8fb9\u680f\u3002 \u5728\u4fa7\u8fb9\u680f\u5185\uff0c\u70b9\u51fb\u300cData Sources\u300d\u3002 \u9009\u62e9\u300cAdd New\u300d\u3002 \u9009\u62e9\u300cPrometheus\u300d\u4f5c\u4e3a\u6570\u636e\u6e90\u3002 \u8bbe\u7f6e Prometheus \u670d\u52a1\u7684 URL\uff08\u5728\u672c\u4f8b\u4e2d\u4e3a\uff1ahttp:\/\/localhost:9090\/\uff09\u3002 \u70b9\u51fb \u300cAdd\u300d\u5373\u53ef\u6d4b\u8bd5\u8fde\u63a5\u5e76\u4fdd\u5b58\u4e3a\u65b0\u7684\u6570\u636e\u6e90\u3002  \u5982\u4e0a\u914d\u7f6e\u5e94\u5f53\u7c7b\u4f3c\uff1a\n  \u73b0\u5728\u4f60\u53ef\u4ee5\u521b\u5efa\u7b2c\u4e00\u4e2a\u770b\u677f\uff08Dashboard\uff09\u7528\u4e8e\u5c55\u793a Prometheus \u6536\u96c6\u5230\u7684\u4fe1\u606f\u4e86\u3002\u4f60\u4e5f\u53ef\u4ee5\u4ece\u5171\u4eab\u770b\u677f\u96c6\u5408\u5bfc\u5165\u4e00\u4e9b\u73b0\u6210\u7684\u770b\u677f\u3002\n\u5982\u4e0b\u662f\u4e00\u4e2a\u4f8b\u5b50\u770b\u677f\uff0c\u5b83\u67e5\u8be2\u4e86\u8282\u70b9\u670d\u52a1\u5668\u7684 CPU \u4f7f\u7528\u91cf\u5e76\u5c55\u793a\u5728 Grafana \u5185\uff1a\n  \u5728\u672c\u6559\u7a0b\u4e2d\uff0c\u6211\u4eec\u5b89\u88c5\u4e86 Prometheus \u670d\u52a1\u4ee5\u53ca\u4e24\u4e2a\u6570\u636e\u5bfc\u51fa\u5668\u4f9b Prometheus \u6293\u53d6\uff0c\u5e76\u914d\u7f6e\u4e86\u7531 Peometheus \u63d0\u4f9b\u6570\u636e\u7684 Grafana \u770b\u677f\u3002\u4e0d\u8981\u72b9\u8c6b\uff0c\u5feb\u53bb\u770b\u770b Prometheus \u548c Grafana \u7684\u5b98\u65b9\u6587\u6863\u5427\u3002\n\u8bd1\u8005\u63a8\u8350 \u62d3\u5c55\u9605\u8bfb\uff1a\n https:\/\/yunlzheng.gitbook.io\/prometheus-book\/ https:\/\/prometheus.io\/docs\/guides\/node-exporter\/ https:\/\/songjiayang.gitbooks.io\/prometheus\/content\/ https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-install-prometheus-on-ubuntu-16-04  \u63a8\u8350\u770b\u677f\uff1a\n  Node Exporter\n https:\/\/grafana.com\/dashboards\/405 https:\/\/grafana.com\/dashboards\/1860    Process Exporter\n https:\/\/grafana.com\/dashboards\/249 https:\/\/grafana.com\/dashboards\/8378   ","permalink":"https:\/\/wi1dcard.dev\/posts\/configure-prometheus-monitoring-with-grafana\/","summary":"<blockquote>\n<p>\u8bd1\u8005\u5e8f\uff1aPrometheus \u662f\u670d\u52a1\u5668\u76d1\u63a7\u7cfb\u7edf\u7684\u540e\u8d77\u4e4b\u79c0\uff0c\u53ef\u4ee5\u548c Kubernetes \u5b8c\u7f8e\u7ed3\u5408\u7528\u4e8e\u76d1\u63a7\u5927\u91cf\u96c6\u7fa4\u548c\u5e94\u7528\u3002Grafana \u662f\u4e00\u6b3e\u6570\u636e\u53ef\u89c6\u5316\u770b\u677f\uff0c\u53ef\u6307\u5b9a\u591a\u4e2a\u6570\u636e\u6e90\u6267\u884c\u67e5\u8be2\uff0c\u5c06\u67af\u71e5\u7684\u6570\u636e\u8f6c\u5316\u4e3a\u591a\u7ef4\u5ea6\u7684\u9762\u677f\u3002\u4e24\u8005\u5747\u4e3a\u5f00\u6e90\u9879\u76ee\uff0c\u901a\u8fc7\u914d\u7f6e\u53ef\u5b9e\u73b0\u76f4\u89c2\u5f3a\u5927\u7684\u76d1\u63a7\u3001\u62a5\u8b66\u3001\u5206\u6790\u7cfb\u7edf\uff0c\u5b9e\u5c5e\u8fd0\u7ef4\u795e\u5668\u3002<\/p>\n<\/blockquote>","title":"\u914d\u7f6e Prometheus \u670d\u52a1\u5668\u76d1\u63a7\u548c Grafana \u770b\u677f"},{"content":"0x00 \u5e9f\u8bdd \ud83c\udf89 Tada\uff5e \u535a\u5ba2\u7115\u65b0\u4e3b\u9898\u3002\n\u5b9e\u5728\u53d7\u4e0d\u4e86\u539f\u6765\u90a3\u4e2a\u4e3b\u9898\u4e86\uff0c\u5c24\u5176\u662f\u5728\u88ab\u6211\u4eec\u516c\u53f8 CTO \u90fd\u5acc\u5f03\u4e11\u7684\u60c5\u51b5\u4e0b\u3002\u518d\u52a0\u4e0a\u4ee5\u4e0b\u51e0\u4e2a\u539f\u56e0\uff1a\n \u8be5\u4e3b\u9898 GitHub Repo \u51e0\u4e4e\u505c\u6b62\u7ef4\u62a4\uff0c\u51e0\u5468\u624d\u9c9c\u6709\u51e0\u6b21 Commit\u3002 \u4ece\u6211\u5f00\u59cb\u4f7f\u7528\u8be5\u4e3b\u9898\u4ee5\u6765\uff0c\u5f00\u53d1\u4e2d\u7684 Nexus \u4e3b\u9898\u6837\u5f0f\u4f9d\u65e7\u5728\u5f00\u53d1\u4e2d\uff0c2.0 \u7248\u672c\u4e5f\u662f\u4e00\u6837\u3002 \u914d\u7f6e\u9879\u5b9e\u5728\u662f\u592a\u592a\u592a\u591a\u4e86\uff0c\u591a\u5230\u7ecf\u5e38\u6539\u52a8\u4e00\u4e2a\u5730\u65b9\u5c31\u5f15\u8d77\u5947\u602a\u7684\u95ee\u9898\uff0c\u4e14\u5bf9\u4e8e\u914d\u7f6e\u6587\u4ef6\u7684\u683c\u5f0f\u68c0\u67e5\u57fa\u672c\u4e3a\u96f6\u3002 \u6587\u6863\u4e0d\u660e\u786e\uff0c\u5341\u5206\u9690\u6666\uff0c\u5185\u7f6e\u529f\u80fd\u4f17\u591a\u4f46\u9c7c\u9f99\u6df7\u6742\u3002 \u6700\u8fd1 \u6587\u6863\u57df\u540d\u8bc1\u4e66\u8fc7\u671f \u65e0\u6cd5\u8bbf\u95ee\u3002 &hellip;  \u4e0d\u80fd\u5fcd\u4e0d\u80fd\u5fcd\u3002\u4e00\u6c14\u4e4b\u4e0b\u5f00\u59cb\u4e86\u75af\u72c2\u7684\u8fc1\u79fb\uff0c\u7ecf\u8fc7\u51e0\u4e2a\u5c0f\u65f6\u7684\u6298\u817e\u57fa\u672c\u5b8c\u6210\uff0c\u7b80\u5386\u7684\u6392\u7248\u4e5f\u66f4\u52a0\u660e\u6717\u4e86\u3002\n0x01 \u5f15\u5b50 \u5f53\u7136\u8fd9\u4e0d\u662f\u8fd9\u7bc7\u6587\u7ae0\u7684\u76ee\u7684\uff08\u8fd9\u4e48\u6c34\u7684\u6587\u6211\u81ea\u5df1\u90fd\u4e0d\u597d\u610f\u601d\u53d1\u51fa\u6765\uff09\uff0c\u5728\u5207\u6362\u4e3b\u9898\u7684\u8fc7\u7a0b\u4e2d\u53d1\u73b0\u4e00\u4e2a\u95ee\u9898\u3002\n\u539f\u672c\u6211\u4f7f\u7528\u7684\u662f Material\uff0c\u8be5\u4e3b\u9898\u5c06\u914d\u7f6e\u6587\u4ef6 _config.yml \u5728\u4ed3\u5e93\u5185\u547d\u540d\u4e3a _config.template.yml\uff0c\u4e14\u5728 .gitignore \u6587\u4ef6\u4e2d\u5ffd\u7565\u4e86 _config.yml\u3002\u6b63\u5982\u5176\u5b98\u65b9\u6587\u6863\u6240\u8bf4\uff1a\n \u4e3a\u9632\u6b62\u9020\u6210\u51b2\u7a81\uff0c\u4e3b\u9898\u4ee5 _config.template.yml \u6587\u4ef6\u53d6\u4ee3 _config.yml \u6587\u4ef6\uff0c\u7528\u4ee5\u53c2\u8003\u914d\u7f6e\u3002 \u9700\u8981\u624b\u52a8\u5c06 material \u6587\u4ef6\u5939\u4e2d\u7684 _config.template.yml \u590d\u5236\u4e00\u4efd\u5e76\u91cd\u547d\u540d\u4e3a _config.yml\u3002\n \u8fd9\u7ed9\u4e3b\u9898\u7684\u4f7f\u7528\u8005\u5e26\u6765\u4e86\u6781\u5927\u7684\u4fbf\u5229\u3002\u6211\u4eec Git Clone \u4e0b\u6765\u540e\uff0c\u590d\u5236\u4e00\u4efd _config.template.yml \u5230 _config.yml\uff0c\u968f\u540e\u4fbf\u80fd\u591f\u4efb\u610f\u4fee\u6539\u4e3b\u9898\u914d\u7f6e\uff1b\u540c\u65f6\u4e5f\u53ef\u4ee5\u968f\u610f\u5730\u5207\u6362\u4e3b\u9898\u4ed3\u5e93\u7684\u5206\u652f\u3001Pull \u4ee3\u7801\uff0c\u4e0d\u4f1a\u5f71\u54cd\u5230 _config.yml \u6587\u4ef6\u3002\n\u8fd9\u4e2a\u8bbe\u8ba1\u8ba9\u6211\u60f3\u8d77 Laravel \u7684 .env.example\uff0c\u4e24\u8005\u795e\u4f3c\u3002\n\u4f46\u662f\u8fd9\u6b21\u66f4\u6362\u4e3b\u9898\uff0c\u5207\u6362\u4e3a Indigo \u5c31\u6ca1\u6709\u8fd9\u4e48\u5e78\u8fd0\u4e86\u3002\u8be5\u4e3b\u9898\u5e76\u6ca1\u6709\u4f7f\u7528 _config.template.yml \u7684\u65b9\u5f0f\u7ba1\u7406\u914d\u7f6e\u6587\u4ef6\uff0c\u800c\u662f\u76f4\u63a5\u5728\u4ed3\u5e93\u5185\u63d0\u4ea4\u4e86\u4e00\u4e2a\u56fa\u5b9a\u7684 _config.yml\u3002\n\u8fd9\u5c31\u9020\u6210\uff1a\n \u8981\u4e48\u6211 Clone \u540e\u6c38\u8fdc\u4e0d Pull\uff0c\u8fd9\u610f\u5473\u7740\u65e0\u6cd5\u81ea\u7531\u5730\u66f4\u65b0\u7248\u672c\u3002 \u8981\u4e48\u6211\u5c31\u9700\u8981\u5728\u6bcf\u6b21\u66f4\u65b0\u65f6\uff0c\u5148 Stash \u518d Pull \u518d Pop Stash\u3002 \u6216\u8005\u5e72\u8106\u5220\u9664 .git \u76ee\u5f55\uff0c\u91c7\u7528\u4f20\u7edf\u4e0b\u8f7d\u3001\u89e3\u538b\u7684\u65b9\u5f0f\u66f4\u65b0\uff08\u5751\uff09\u3002  \u53e6\u5916\uff0c\u6211\u4f7f\u7528 Git \u6765\u7ba1\u7406\u6211\u7684 Hexo \u535a\u5ba2\u6e90\u7801\uff0c\u7531\u4e8e\u8be5\u4e3b\u9898\u7684\u4ed3\u5e93\u5df2\u7ecf\u7ba1\u7406\u4e86 _config.yml\uff0c\u56e0\u6b64\u6211\u5728\u8be5\u914d\u7f6e\u6587\u4ef6\u6240\u505a\u7684\u4fee\u6539\u65e0\u6cd5\u63d0\u4ea4\u5230\u6211\u81ea\u5df1\u7684\u535a\u5ba2\u4ed3\u5e93\u5185\uff0c\u8fd9\u8ba9\u6211\u5185\u5fc3\u5341\u5206\u6ca1\u5e95\u3002\u4e07\u4e00\u54ea\u5929\u7535\u8111\u4e22\u5931\uff0c\u8be5\u914d\u7f6e\u6587\u4ef6\u5c31\u65e0\u6cd5\u901a\u8fc7\u8fdc\u7aef Git \u4ed3\u5e93\u627e\u56de\u4e86\u3002\n0x02 \u89e3\u51b3 \u76ee\u524d\u6211\u80fd\u60f3\u5230\u7684\u6bd4\u8f83\u5408\u9002\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u5c31\u662f\u4f7f\u7528 Git Subtree\u3002\n\u4e0e Git Submodule \u4e0d\u540c\uff0c\u5728\u901a\u8fc7 Subtree \u529f\u80fd\u5f15\u5165\u5b50\u4ed3\u5e93\u540e\uff0c\u5b50\u4ed3\u5e93\u5185\u7684\u6587\u4ef6\uff0c\u4f9d\u65e7\u4f1a\u539f\u5c01\u4e0d\u52a8\u5730\u51fa\u73b0\u5728\u672c\u4ed3\u5e93\u5185\uff0c\u5c31\u50cf cp \u8fc7\u6765\u7684\u4e00\u6837\u3002\u6216\u8005\u4f60\u53ef\u4ee5\u5e72\u8106\u5c31\u628a\u5b83\u7406\u89e3\u4e3a\u590d\u5236\uff0c\u56e0\u4e3a\u5728\u6587\u4ef6\u7cfb\u7edf\u800c\u975e Git \u7684\u5c42\u9762\u4e0a\u6765\u770b\uff0c\u5b83\u7684\u786e\u5c31\u662f cp \u4e86\u4e00\u4efd\u3002\n\u4f46\u662f\uff0cSubtree \u8fdc\u8fdc\u6ca1\u6709\u90a3\u4e48\u7b80\u5355\uff0cGit \u4f1a\u5728\u672c\u4ed3\u5e93\u7684\u63d0\u4ea4\u8bb0\u5f55\u5185\u6dfb\u52a0\u4e00\u6761\u7279\u6b8a\u7684 Merge Commit\uff1b\u5728\u4ee5\u540e\u66f4\u65b0 Subtree \u7684\u8fc7\u7a0b\u4e2d\uff0cGit \u4fbf\u4f1a\u53bb\u67e5\u627e\u90a3\u6b21 Merge Commit\uff0c\u4ece\u800c\u786e\u5b9a Diff \u7684\u5185\u5bb9\u5e76\u5e94\u7528\u3002\n\u7531\u6b64\uff0c\u6211\u53ef\u4ee5\u5148\u4f7f\u7528 Subtree \u5f15\u5165\u8be5\u4e3b\u9898\u5230 themes \u76ee\u5f55\u4e0b\uff0c\u4fee\u6539 _config.yml \u6587\u4ef6\u540e\u7167\u6837\u80fd\u591f\u63d0\u4ea4\u5230\u6211\u7684\u535a\u5ba2\u4ed3\u5e93\uff0c\u4e14\u4e0d\u5f71\u54cd\u6211\u7684\u4e0b\u6b21 Pull\uff0c\u6709\u51b2\u7a81\u65f6\u624b\u52a8 Merge \u5373\u53ef\u3002\nOK\uff0c\u8bf4\u4e86\u8fd9\u4e48\u591a\uff0c\u6765\u770b\u770b\u5b9e\u9645\u64cd\u4f5c\u547d\u4ee4\u3002\ngit subtree add \\  --prefix themes\/indigo \\  git@github.com:yscoder\/hexo-theme-indigo.git card \\  --squash \u5728\u4ee5\u4e0a\u4f8b\u5b50\u4e2d\uff1a\n themes\/indigo \u53ef\u4ee5\u7406\u89e3\u4e3a\u5f15\u5165\u7684 Subtree \u7684\u5b58\u653e\u8def\u5f84\uff1b git@github.com:yscoder\/hexo-theme-indigo.git\u662f\u8be5\u4e3b\u9898\u7684 GitHub \u4ed3\u5e93\u94fe\u63a5\uff0c card \u662f\u8be5\u4e3b\u9898\u4ed3\u5e93\u7684\u7279\u5b9a\u5206\u652f\u540d\uff08\u4f8b\u5982\u901a\u5e38\u4e3a master\uff09 --squash \u8868\u793a\u538b\u7f29\u6b64 Subtree \u6b64\u524d\u7684\u63d0\u4ea4\u8bb0\u5f55\u4e3a\u5355\u6761\uff0c\u6982\u5ff5\u7c7b\u4f3c\u4e8e Git Rebase \u65f6\u7684 Squash\u3002  \u4ee5\u4e0a\uff0c\u6210\u529f\u5f15\u5165\u4e86\u8be5\u4ed3\u5e93 card \u5206\u652f\u7684\u4ee3\u7801\u5230 themes\/indigo \u76ee\u5f55\u3002\n\u5b9e\u9645\u4e0a\uff0c\u4ee5\u4e0a\u7684 card \u53ef\u4ee5\u66ff\u6362\u4e3a\u4efb\u610f Git Ref\uff0c\u8fd9\u4e2a\u6982\u5ff5\u5728\u4f7f\u7528 Git \u65f6\u7ecf\u5e38\u51fa\u73b0\uff0c\u53ef\u4ee5\u662f\u5206\u652f\u540d\u3001\u4e00\u6b21\u7279\u5b9a\u7684\u63d0\u4ea4\u54c8\u5e0c\u6216\u662f\u67d0\u4e2a Tag \u7684\u540d\u5b57\u3002\n\u5728\u540e\u7eed\u66f4\u65b0\u4ee3\u7801\u65f6\uff0c\u4f7f\u7528 git subtree pull \u547d\u4ee4\u5373\u53ef\u3002\u6b64\u5904\u4e0d\u518d\u8d58\u8ff0\u3002\n0x03 \u540e\u7eed&hellip; \u66f4\u591a\u5173\u4e8e Subtree \u7684\u8be6\u7ec6\u539f\u7406\u548c\u64cd\u4f5c\uff0c\u53ef\u4ee5\u67e5\u770b\u8fd9\u7bc7\u6587\u7ae0\u3002\n\u5982\u679c\u4f60\u6709\u66f4\u597d\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u6b22\u8fce\u901a\u8fc7\u90ae\u4ef6\u6216\u8bc4\u8bba\u8054\u7cfb\u6211\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/manage-hexo-themes-with-git-subtree\/","summary":"0x00 \u5e9f\u8bdd \ud83c\udf89 Tada\uff5e \u535a\u5ba2\u7115\u65b0\u4e3b\u9898\u3002\n\u5b9e\u5728\u53d7\u4e0d\u4e86\u539f\u6765\u90a3\u4e2a\u4e3b\u9898\u4e86\uff0c\u5c24\u5176\u662f\u5728\u88ab\u6211\u4eec\u516c\u53f8 CTO \u90fd\u5acc\u5f03\u4e11\u7684\u60c5\u51b5\u4e0b\u3002\u518d\u52a0\u4e0a\u4ee5\u4e0b\u51e0\u4e2a\u539f\u56e0\uff1a\n \u8be5\u4e3b\u9898 GitHub Repo \u51e0\u4e4e\u505c\u6b62\u7ef4\u62a4\uff0c\u51e0\u5468\u624d\u9c9c\u6709\u51e0\u6b21 Commit\u3002 \u4ece\u6211\u5f00\u59cb\u4f7f\u7528\u8be5\u4e3b\u9898\u4ee5\u6765\uff0c\u5f00\u53d1\u4e2d\u7684 Nexus \u4e3b\u9898\u6837\u5f0f\u4f9d\u65e7\u5728\u5f00\u53d1\u4e2d\uff0c2.0 \u7248\u672c\u4e5f\u662f\u4e00\u6837\u3002 \u914d\u7f6e\u9879\u5b9e\u5728\u662f\u592a\u592a\u592a\u591a\u4e86\uff0c\u591a\u5230\u7ecf\u5e38\u6539\u52a8\u4e00\u4e2a\u5730\u65b9\u5c31\u5f15\u8d77\u5947\u602a\u7684\u95ee\u9898\uff0c\u4e14\u5bf9\u4e8e\u914d\u7f6e\u6587\u4ef6\u7684\u683c\u5f0f\u68c0\u67e5\u57fa\u672c\u4e3a\u96f6\u3002 \u6587\u6863\u4e0d\u660e\u786e\uff0c\u5341\u5206\u9690\u6666\uff0c\u5185\u7f6e\u529f\u80fd\u4f17\u591a\u4f46\u9c7c\u9f99\u6df7\u6742\u3002 \u6700\u8fd1 \u6587\u6863\u57df\u540d\u8bc1\u4e66\u8fc7\u671f \u65e0\u6cd5\u8bbf\u95ee\u3002 &hellip;  \u4e0d\u80fd\u5fcd\u4e0d\u80fd\u5fcd\u3002\u4e00\u6c14\u4e4b\u4e0b\u5f00\u59cb\u4e86\u75af\u72c2\u7684\u8fc1\u79fb\uff0c\u7ecf\u8fc7\u51e0\u4e2a\u5c0f\u65f6\u7684\u6298\u817e\u57fa\u672c\u5b8c\u6210\uff0c\u7b80\u5386\u7684\u6392\u7248\u4e5f\u66f4\u52a0\u660e\u6717\u4e86\u3002","title":"\u4f7f\u7528 Git Subtree \u7ba1\u7406 Hexo \u4e3b\u9898"},{"content":"\u539f\u672c\u4eca\u665a\u6253\u7b97\u65e9\u7761\uff0c\u7136\u800c\u7761\u610f\u4e00\u8fc7\u968f\u4e4b\u800c\u6765\u5c31\u662f\u5f7b\u5e95\u7684\u6e05\u9192\u3002\n\u8fd1\u671f\uff08emmmm&hellip; \u51e0\u4e2a\u6708\u524d\uff09\u8df3\u69fd\u540e\u4e00\u76f4\u6ca1\u6709\u518d\u7ee7\u7eed\u7f16\u5199\u535a\u5ba2\uff0c\u8fde\u7eed\u8df3\u7968\uff0c\u4e00\u6643\u5230\u4e86 2018 \u7684\u5e74\u5e95\u3002\n\u4e0d\u8fc7\u8fd8\u662f\u505c\u4e0d\u4e0b\u6765\u81ea\u5df1\u9700\u8981\u5199\u70b9\u4ec0\u4e48\u7684\u4e60\u60ef\u3002\u7531\u4e8e\u60f3\u8981\u300c\u79fb\u6c11\u300d\u7684\u503e\u5411\u8d8a\u6765\u8d8a\u5f3a\u70c8\uff0c\u4e8e\u662f\u4fbf\u5f00\u542f\u4e86\u300c\u7ffb\u8bd1\u300d\u7684\u65c5\u7a0b\u3002\n\u5e0c\u671b\u51e0\u4e2a\u6708\u540e\u80fd\u591f\u5728\u4e0d\u65ad\u7684\u5b9e\u8df5\u548c\u953b\u70bc\u4e2d\uff0c\u63d0\u9ad8\u81ea\u5df1\u7684\u82f1\u6587\u8bfb\u5199\u6c34\u5e73\u5427\u3002\n\u6709\u5174\u8da3\u7684\u670b\u53cb\u53ef\u4ee5\u5173\u6ce8\u4e0b\u6211\u7684 Laravel-China ID\u3002\n\u5728\u5f00\u59cb\u65e5\u6e10\u6c89\u8ff7 Laravel-China \u7684\u540c\u65f6\uff0c\u6211\u51b3\u5b9a\u79bb\u5f00 Gitee \u2014\u2014 \u4e5f\u5c31\u662f\u7801\u4e91\u4e86\u3002\n\u6216\u8bb8\u56fd\u5185\u7684\u5f00\u6e90\u793e\u533a\u771f\u7684\u505a\u4e0d\u8d77\u6765\uff1a\n\u8fd8\u6709\uff0c\u4e5f\u6253\u7b97\u8ba9\u5fae\u4fe1\u9000\u51fa\u6211\u300c\u4e3b\u529b\u804a\u5929\u5de5\u5177\u300d\u7684\u821e\u53f0\u4e86\uff0c\u6539\u7528\u5e72\u51c0\u7b80\u5355\u5b89\u5168\u7684 Telegram\uff0c\u524d\u51e0\u5929\u5df2\u7ecf\u66f4\u65b0\u8fc7\u4e86\u7b80\u5386\uff0c\u53bb\u6389\u4e86\u5fae\u4fe1\u4e8c\u7ef4\u7801\u3002\n2019 \u5e74\uff0c\u5e0c\u671b\u81ea\u5df1\u5728\u6280\u672f\u65b9\u9762\uff0c\u80fd\u591f\u5c06\u540e\u7aef\u9886\u57df\u6316\u5f97\u66f4\u6df1\uff0c\u82f1\u8bed\u6c34\u5e73\u83b7\u5f97\u8d28\u7684\u63d0\u5347\uff1b\u751f\u6d3b\u65b9\u9762\uff0c\u548c\u5973\u670b\u53cb\u4fdd\u6301\u7f8e\u597d\u5e78\u798f\uff0c\u987a\u4fbf\u88c5\u70b9\u597d\u6211\u4eec\u7684\u5bb6\uff0c\u8ddf\u968f\u6211\u5d69\u7684\u811a\u6b65\uff0c\u591a\u7ec3\u7ec3\u53a8\u827a\u4e5f\u4e0d\u9519\uff1b\u5176\u4ed6\uff0c\u5e73\u5b89\u5065\u5eb7\u5c31\u597d\u3002\n\u2014\u2014\u300c\u82f1\u96c4\u4eec\u4ef0\u4ed7\u5b64\u80c6\uff0c\u6211\u4ef0\u4ed7\u4f60\u7684\u7231\uff0c\u53bb\u901a\u5173\u3002\u300d\n","permalink":"https:\/\/wi1dcard.dev\/posts\/hello-2019\/","summary":"\u539f\u672c\u4eca\u665a\u6253\u7b97\u65e9\u7761\uff0c\u7136\u800c\u7761\u610f\u4e00\u8fc7\u968f\u4e4b\u800c\u6765\u5c31\u662f\u5f7b\u5e95\u7684\u6e05\u9192\u3002\n\u8fd1\u671f\uff08emmmm&hellip; \u51e0\u4e2a\u6708\u524d\uff09\u8df3\u69fd\u540e\u4e00\u76f4\u6ca1\u6709\u518d\u7ee7\u7eed\u7f16\u5199\u535a\u5ba2\uff0c\u8fde\u7eed\u8df3\u7968\uff0c\u4e00\u6643\u5230\u4e86 2018 \u7684\u5e74\u5e95\u3002\n\u4e0d\u8fc7\u8fd8\u662f\u505c\u4e0d\u4e0b\u6765\u81ea\u5df1\u9700\u8981\u5199\u70b9\u4ec0\u4e48\u7684\u4e60\u60ef\u3002\u7531\u4e8e\u60f3\u8981\u300c\u79fb\u6c11\u300d\u7684\u503e\u5411\u8d8a\u6765\u8d8a\u5f3a\u70c8\uff0c\u4e8e\u662f\u4fbf\u5f00\u542f\u4e86\u300c\u7ffb\u8bd1\u300d\u7684\u65c5\u7a0b\u3002\n\u5e0c\u671b\u51e0\u4e2a\u6708\u540e\u80fd\u591f\u5728\u4e0d\u65ad\u7684\u5b9e\u8df5\u548c\u953b\u70bc\u4e2d\uff0c\u63d0\u9ad8\u81ea\u5df1\u7684\u82f1\u6587\u8bfb\u5199\u6c34\u5e73\u5427\u3002\n\u6709\u5174\u8da3\u7684\u670b\u53cb\u53ef\u4ee5\u5173\u6ce8\u4e0b\u6211\u7684 Laravel-China ID\u3002\n\u5728\u5f00\u59cb\u65e5\u6e10\u6c89\u8ff7 Laravel-China \u7684\u540c\u65f6\uff0c\u6211\u51b3\u5b9a\u79bb\u5f00 Gitee \u2014\u2014 \u4e5f\u5c31\u662f\u7801\u4e91\u4e86\u3002\n\u6216\u8bb8\u56fd\u5185\u7684\u5f00\u6e90\u793e\u533a\u771f\u7684\u505a\u4e0d\u8d77\u6765\uff1a\n\u8fd8\u6709\uff0c\u4e5f\u6253\u7b97\u8ba9\u5fae\u4fe1\u9000\u51fa\u6211\u300c\u4e3b\u529b\u804a\u5929\u5de5\u5177\u300d\u7684\u821e\u53f0\u4e86\uff0c\u6539\u7528\u5e72\u51c0\u7b80\u5355\u5b89\u5168\u7684 Telegram\uff0c\u524d\u51e0\u5929\u5df2\u7ecf\u66f4\u65b0\u8fc7\u4e86\u7b80\u5386\uff0c\u53bb\u6389\u4e86\u5fae\u4fe1\u4e8c\u7ef4\u7801\u3002\n2019 \u5e74\uff0c\u5e0c\u671b\u81ea\u5df1\u5728\u6280\u672f\u65b9\u9762\uff0c\u80fd\u591f\u5c06\u540e\u7aef\u9886\u57df\u6316\u5f97\u66f4\u6df1\uff0c\u82f1\u8bed\u6c34\u5e73\u83b7\u5f97\u8d28\u7684\u63d0\u5347\uff1b\u751f\u6d3b\u65b9\u9762\uff0c\u548c\u5973\u670b\u53cb\u4fdd\u6301\u7f8e\u597d\u5e78\u798f\uff0c\u987a\u4fbf\u88c5\u70b9\u597d\u6211\u4eec\u7684\u5bb6\uff0c\u8ddf\u968f\u6211\u5d69\u7684\u811a\u6b65\uff0c\u591a\u7ec3\u7ec3\u53a8\u827a\u4e5f\u4e0d\u9519\uff1b\u5176\u4ed6\uff0c\u5e73\u5b89\u5065\u5eb7\u5c31\u597d\u3002","title":"\u6f2b\u8c08 2019"},{"content":"\u4e8c\u7ea7\u57df\u540d\u7ed1\u5b9a\u5b50\u76ee\u5f55 Nginx + PHP-FPM \u914d\u7f6e\uff0c\u5185\u7f6e Laravel \u91cd\u5199\u89c4\u5219\uff0c\u53ef\u7528\u4e8e\u672c\u5730\u591a\u9879\u76ee\u5f00\u53d1\u3002\n\u5728 Nginx \u7684\u7ad9\u70b9\u914d\u7f6e\u76ee\u5f55\u65b0\u589e\u7ad9\u70b9\u540e\uff0c\u589e\u52a0\u4ee5\u4e0b\u4ee3\u7801\u5757\u5373\u53ef\u3002\nserver_name ~^(.*)\\.laravel\\.test$; # \u6b63\u5219\u4e8c\u7ea7\u57df\u540d root \/Users\/jootu\/web\/$1\/public; index index.html index.htm index.php; location \/ { try_files $uri $uri\/ \/index.php?$query_string; } ","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-nginx-subdomains\/","summary":"\u4e8c\u7ea7\u57df\u540d\u7ed1\u5b9a\u5b50\u76ee\u5f55 Nginx + PHP-FPM \u914d\u7f6e\uff0c\u5185\u7f6e Laravel \u91cd\u5199\u89c4\u5219\uff0c\u53ef\u7528\u4e8e\u672c\u5730\u591a\u9879\u76ee\u5f00\u53d1\u3002\n\u5728 Nginx \u7684\u7ad9\u70b9\u914d\u7f6e\u76ee\u5f55\u65b0\u589e\u7ad9\u70b9\u540e\uff0c\u589e\u52a0\u4ee5\u4e0b\u4ee3\u7801\u5757\u5373\u53ef\u3002\nserver_name ~^(.*)\\.laravel\\.test$; # \u6b63\u5219\u4e8c\u7ea7\u57df\u540d root \/Users\/jootu\/web\/$1\/public; index index.html index.htm index.php; location \/ { try_files $uri $uri\/ \/index.","title":"Laravel \u4e8c\u7ea7\u57df\u540d\u7ed1\u5b9a\u5b50\u76ee\u5f55 Nginx \u914d\u7f6e"},{"content":"\u4f9d\u8d56 Node.js \u89e3\u6790 JSON \u4fe1\u606f\uff0c\u51e0\u6761 Bash \u547d\u4ee4\u5c31\u80fd\u62ff\u5230\u5546\u54c1\u4fe1\u606f\u4e86\u3002\n\u6dd8\u5b9d\u3002\n# \u6d4b\u8bd5 URL URL=&#34;https:\/\/item.taobao.com\/item.htm?id=560121532731&#34; CODE=`curl -sS $URL | awk &#39;\/var g_config = {\/,\/};\/&#39; | iconv -f gbk -t utf-8` echo &#34;var location = {}; $CODEconsole.log (g_config)&#34; | node \u5929\u732b\u3002\n# \u6d4b\u8bd5 URL URL=&#34;https:\/\/detail.tmall.com\/item.htm?id=37769192030&#34; CODE=`curl -sS $URL | iconv -f gbk -t utf-8 | grep dsc.taobaocdn.com` echo &#34;var code= $CODE; console.log (code)&#34; | node ","permalink":"https:\/\/wi1dcard.dev\/posts\/taobao-tmall-crawller\/","summary":"\u4f9d\u8d56 Node.js \u89e3\u6790 JSON \u4fe1\u606f\uff0c\u51e0\u6761 Bash \u547d\u4ee4\u5c31\u80fd\u62ff\u5230\u5546\u54c1\u4fe1\u606f\u4e86\u3002\n\u6dd8\u5b9d\u3002\n# \u6d4b\u8bd5 URL URL=&#34;https:\/\/item.taobao.com\/item.htm?id=560121532731&#34; CODE=`curl -sS $URL | awk &#39;\/var g_config = {\/,\/};\/&#39; | iconv -f gbk -t utf-8` echo &#34;var location = {}; $CODEconsole.","title":"\u6dd8\u5b9d\u5929\u732b\u5546\u54c1\u4fe1\u606f\u7b80\u6613\u722c\u866b"},{"content":"\u524d\u8a00 \u6700\u8fd1\u56fd\u5e86\u671f\u95f4\u6ca1\u7ee7\u7eed\u5f00\u53d1\u9879\u76ee\uff0c\u636e\u8bf4\u8981\u6709\u5927\u53d8\u52a8\uff0c\u7b49\u56fd\u5e86\u540e\u5f00\u4f1a\u8ba8\u8bba\uff0c\u5185\u5fc3\u6709\u70b9\u65b9\u5f20\u3002\n Updated: \u56fd\u5e86\u540e\u7684\u7b2c\u4e00\u5929\uff0c\u679c\u7136\u780d\u4e86\u3002\u96be\u53d7\u3002\n \u8d81\u7740\u5047\u671f\uff0c\u5c01\u88c5\u4e86\u4e24\u4e2a\u6269\u5c55\u5305\u3002\n \u4e2d\u56fd\u884c\u653f\u533a\u5212\u5730\u5740\u5e93 SDK &#43; \u722c\u866b &#43; \u6570\u636e \u767e\u5ea6\u5c0f\u7a0b\u5e8f\u7b2c\u4e09\u65b9 PHP SDK  \u5728\u6784\u5efa\u540e\u8005\u7684\u65f6\u5019\uff0c\u8003\u8651\u5230 PSR-7 \u9010\u6e10\u5728 PHP \u751f\u6001\u5708\u88ab\u5927\u4f17\u63a5\u53d7\uff0c\u7ecf\u8fc7\u659f\u914c\u51b3\u5b9a\u5c06 HTTP \u5ba2\u6237\u7aef\u4e0e SDK \u81ea\u8eab\u903b\u8f91\u5206\u79bb\uff0c\u5b8c\u5168\u9075\u5faa PSR-7\uff0c\u6240\u6709\u8bf7\u6c42\u90fd\u5b9e\u73b0\u4e3a RequestInterface\uff0c\u968f\u540e\u4f7f\u7528\u4efb\u610f\u517c\u5bb9 PSR-7 \u7684\u5ba2\u6237\u7aef\u53d1\u9001\u5373\u53ef\uff0c\u6269\u5c55\u5305\u672c\u8eab\u4e0d\u5173\u6ce8 HTTP \u534f\u8bae\u7684\u6570\u636e\u4f20\u8f93\u3002\n\u4f18\u52bf \u5b9e\u9645\u4e0a\uff0c\u53ef\u66ff\u6362\u7684 HTTP \u5ba2\u6237\u7aef\u597d\u5904\u6709\u5f88\u591a\u3002\n \u652f\u6301\u66f4\u591a\u529f\u80fd\uff0c\u53ef\u81ea\u5b9a\u4e49 HTTP \u5ba2\u6237\u7aef\u8ba9 SDK \u7684\u8bf7\u6c42\u8d70\u4ee3\u7406\u3001\u5e26\u5176\u5b83\u5934\u4fe1\u606f\u7b49\u3002 \u4fdd\u6301\u9879\u76ee\u7cbe\u7b80\u5e72\u7ec3\u3001\u9632\u6b62\u51b2\u7a81\uff0c\u5f53\u4f60\u5df2\u7ecf\u5b89\u88c5\u5176\u5b83 HTTP \u5ba2\u6237\u7aef\u6269\u5c55\u5305\uff0c\u4e0d\u9700\u8981\u518d\u56e0\u4e3a SDK \u7684\u4f9d\u8d56\u4e0d\u5f97\u4e0d\u5b89\u88c5\u53e6\u4e00\u4e2a HTTP \u5ba2\u6237\u7aef\u6269\u5c55\uff0c\u5171\u7528\u5373\u53ef\u3002 \u5982\u679c\u4f60\u7684\u9879\u76ee\u5df2\u7ecf\u5904\u5728\u5f00\u53d1\u4e2d\uff0c\u751a\u81f3\u5df2\u7ecf\u4e0a\u7ebf\uff0c\u53ef\u9632\u6b62\u5df2\u6709\u7684 HTTP \u5ba2\u6237\u7aef\u7248\u672c SDK \u5185\u7684\u51fa\u73b0\u51b2\u7a81\u3002 \u82e5\u67d0\u4e2a HTTP \u5ba2\u6237\u7aef\u51fa\u73b0 BUG\uff0c\u6216\u9879\u76ee\u7ef4\u62a4\u8005\u8dd1\u8def\uff0c\u53ef\u968f\u65f6\u5207\u6362\u53e6\u4e00\u4e2a\u800c\u65e0\u9700\u6539\u52a8 SDK \u672c\u8eab\u3002 \u82e5\u4f60\u7684\u670d\u52a1\u5668\u73af\u5883\uff08\u4f8b\u5982 PHP \u7248\u672c\u95ee\u9898\u7b49\uff09\u4e0d\u652f\u6301\u67d0\u6269\u5c55\uff0c\u53ef\u968f\u65f6\u66ff\u6362\u3002 \u5229\u7528\u8bf8\u5982 Swoole \u8fd9\u7c7b\u795e\u5668\uff0c\u53ef\u8f7b\u677e\u5b9e\u73b0\u534f\u7a0b\u7684 HTTP \u5ba2\u6237\u7aef\uff0c\u53d1\u6325\u5de8\u5927\u6027\u80fd\u4f18\u52bf\u3002 &hellip;  \u63d0\u9192\u81ea\u5df1 \u5728\u4e0d\u65ad\u89e3\u8026\u7684\u540c\u65f6\uff0c\u4e5f\u8981\u65f6\u523b\u9632\u6b62\u6389\u8fdb\u8fc7\u5ea6\u5c01\u88c5\u7684\u602a\u5708\uff1b\u6216\u8bb8\u627e\u5230\u7b80\u5355\u6613\u7528\u4e0e\u7e41\u590d\u5f3a\u5927\u7684\u5e73\u8861\u70b9\uff0c\u624d\u662f\u771f\u6b63\u7684\u6700\u4f73\u5b9e\u8df5\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/psr7-and-httplug\/","summary":"\u524d\u8a00 \u6700\u8fd1\u56fd\u5e86\u671f\u95f4\u6ca1\u7ee7\u7eed\u5f00\u53d1\u9879\u76ee\uff0c\u636e\u8bf4\u8981\u6709\u5927\u53d8\u52a8\uff0c\u7b49\u56fd\u5e86\u540e\u5f00\u4f1a\u8ba8\u8bba\uff0c\u5185\u5fc3\u6709\u70b9\u65b9\u5f20\u3002\n Updated: \u56fd\u5e86\u540e\u7684\u7b2c\u4e00\u5929\uff0c\u679c\u7136\u780d\u4e86\u3002\u96be\u53d7\u3002\n \u8d81\u7740\u5047\u671f\uff0c\u5c01\u88c5\u4e86\u4e24\u4e2a\u6269\u5c55\u5305\u3002\n \u4e2d\u56fd\u884c\u653f\u533a\u5212\u5730\u5740\u5e93 SDK &#43; \u722c\u866b &#43; \u6570\u636e \u767e\u5ea6\u5c0f\u7a0b\u5e8f\u7b2c\u4e09\u65b9 PHP SDK  \u5728\u6784\u5efa\u540e\u8005\u7684\u65f6\u5019\uff0c\u8003\u8651\u5230 PSR-7 \u9010\u6e10\u5728 PHP \u751f\u6001\u5708\u88ab\u5927\u4f17\u63a5\u53d7\uff0c\u7ecf\u8fc7\u659f\u914c\u51b3\u5b9a\u5c06 HTTP \u5ba2\u6237\u7aef\u4e0e SDK \u81ea\u8eab\u903b\u8f91\u5206\u79bb\uff0c\u5b8c\u5168\u9075\u5faa PSR-7\uff0c\u6240\u6709\u8bf7\u6c42\u90fd\u5b9e\u73b0\u4e3a RequestInterface\uff0c\u968f\u540e\u4f7f\u7528\u4efb\u610f\u517c\u5bb9 PSR-7 \u7684\u5ba2\u6237\u7aef\u53d1\u9001\u5373\u53ef\uff0c\u6269\u5c55\u5305\u672c\u8eab\u4e0d\u5173\u6ce8 HTTP \u534f\u8bae\u7684\u6570\u636e\u4f20\u8f93\u3002","title":"PSR-7 \u4e0e HTTPlug"},{"content":"0x00 \u80cc\u666f Laravel \u81ea\u5e26\u8f6f\u5220\u9664\u4f7f\u7528\u7279\u6b8a\u503c NULL \u8868\u793a\u6b64\u8bb0\u5f55\u672a\u88ab\u5220\u9664\u3002\u7531\u6b64\u5f15\u51fa\u4e00\u4e2a\u95ee\u9898\u3002\n\u8bbe\u60f3\uff0c\u67d0\u8868\u5185\u9700\u8981\u5efa\u7acb\u7d22\u5f15\uff0c\u7d22\u5f15\u5b57\u6bb5\u4e3a name, deleted_at\u3002\n\u5047\u8bbe\u6b64\u7d22\u5f15\u6761\u4ef6\u5fc5\u5b9a\u552f\u4e00\uff0c\u53ef\u5efa\u7acb Uniuqe \u7d22\u5f15\u3002\u7136\u800c deleted_at \u5141\u8bb8 NULL \u5b58\u5728\uff0c\u5bfc\u81f4\u7d22\u5f15\u65e0\u6548\uff0c\u5728\u67e5\u8be2\u65f6\u964d\u7ea7\u4e3a Index\u3002\n\u56e0\u6b64\uff0c\u5728\u7edd\u5927\u591a\u6570\u573a\u666f\u4e0b\uff0c\u6211\u4eec\u67e5\u8be2\u672a\u88ab\u5220\u9664\uff08deleted_at IS NULL\uff09\u7684\u6570\u636e\uff0c\u552f\u4e00\u7d22\u5f15\u90fd\u6ca1\u6709\u5375\u7528\u3002\nmysql&gt; EXPLAIN SELECT * FROM `my_tbl`; +----+-------------+--------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | my_tbl | NULL | index | NULL | name_deleted_at | 38 | NULL | 2 | 100.00 | Using index | +----+-------------+--------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) \u4e8e\u662f\uff0c\u4e00\u4e2a\u60f3\u6cd5\u5728\u8111\u6d77\u91cc\u6d6e\u73b0 \u2014\u2014 \u91cd\u5199\u8f6f\u5220\u9664\u5b57\u6bb5\u4e3a\u6574\u578b\u65f6\u95f4\u6233\u3002\n0x01 \u51c6\u5907 Check list:\n Migrations SoftDeletingScope SoftDeletes Trait ???  0x02 Migrations \u7b80\u5355\u3002\n\u65b0\u5efa\u4e00\u4e2a Service Provider\uff0c\u6216\u8005\u76f4\u63a5\u5728 AppServiceProvider \u7684 boot \u65b9\u6cd5\u5185\u6dfb\u52a0\uff1a\nBlueprint::macro(&#39;mySoftDeletes&#39;, function () { $this-&gt;unsignedBigInteger(&#39;deleted_at&#39;)-&gt;default(0); }); \u5728 Migration \u4e2d\u4f7f\u7528 Schema Facade \u521b\u5efa\u8868\u65f6\uff0c\u56de\u8c03\u51fd\u6570\u7684\u53c2\u6570\u4f1a\u88ab\u4f20\u5165\u4e00\u4e2a Blueprint \u5b9e\u4f8b\uff1b\u800c Blueprint \u4f7f\u7528\u4e86 Macroable Trait\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u4efb\u610f\u6269\u5c55\u5b8f\u65b9\u6cd5\uff1b\u8be6\u7ec6\u53ef\u9605\u8bfb Laravel 5.6 \u7ed9 Blueprint \u589e\u52a0\u81ea\u5b9a\u4e49\u65b9\u6cd5\u3002\n0x03 SoftDeletingScope \u65b0\u5efa\u4e00\u4e2a Class\uff0c\u5b9e\u73b0 Scope \u63a5\u53e3\u5373\u53ef\u3002\nnamespace App\\Scopes; use Illuminate\\Database\\Eloquent\\Builder; use Illuminate\\Database\\Eloquent\\Model; use Illuminate\\Database\\Eloquent\\Scope; class MySoftDeletingScope implements Scope { \/** * All of the extensions to be added to the builder. * * @var array *\/ protected $extensions = [&#39;Restore&#39;, &#39;WithTrashed&#39;, &#39;WithoutTrashed&#39;, &#39;OnlyTrashed&#39;]; \/** * Apply the scope to a given Eloquent query builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @param \\Illuminate\\Database\\Eloquent\\Model $model * @return void *\/ public function apply(Builder $builder, Model $model) { $builder-&gt;where($model-&gt;getQualifiedDeletedAtColumn(), &#39;=&#39;, 0); } \/** * Extend the query builder with the needed functions. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return void *\/ public function extend(Builder $builder) { foreach ($this-&gt;extensions as $extension) { $this-&gt;{&#34;add{$extension}&#34;}($builder); } $builder-&gt;onDelete(function (Builder $builder) { $column = $this-&gt;getDeletedAtColumn($builder); return $builder-&gt;update([ $column =&gt; $builder-&gt;getModel()-&gt;freshTimestamp()-&gt;timestamp, ]); }); } \/** * Get the &#34;deleted at&#34; column for the builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return string *\/ protected function getDeletedAtColumn(Builder $builder) { if (count((array) $builder-&gt;getQuery()-&gt;joins) &gt; 0) { return $builder-&gt;getModel()-&gt;getQualifiedDeletedAtColumn(); } return $builder-&gt;getModel()-&gt;getDeletedAtColumn(); } \/** * Add the restore extension to the builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return void *\/ protected function addRestore(Builder $builder) { $builder-&gt;macro(&#39;restore&#39;, function (Builder $builder) { $builder-&gt;withTrashed(); return $builder-&gt;update([$builder-&gt;getModel()-&gt;getDeletedAtColumn() =&gt; 0]); }); } \/** * Add the with-trashed extension to the builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return void *\/ protected function addWithTrashed(Builder $builder) { $builder-&gt;macro(&#39;withTrashed&#39;, function (Builder $builder, $withTrashed = true) { if (! $withTrashed) { return $builder-&gt;withoutTrashed(); } return $builder-&gt;withoutGlobalScope($this); }); } \/** * Add the without-trashed extension to the builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return void *\/ protected function addWithoutTrashed(Builder $builder) { $builder-&gt;macro(&#39;withoutTrashed&#39;, function (Builder $builder) { $model = $builder-&gt;getModel(); $builder-&gt;withoutGlobalScope($this)-&gt;where( $model-&gt;getQualifiedDeletedAtColumn(), &#39;=&#39;, 0 ); return $builder; }); } \/** * Add the only-trashed extension to the builder. * * @param \\Illuminate\\Database\\Eloquent\\Builder $builder * @return void *\/ protected function addOnlyTrashed(Builder $builder) { $builder-&gt;macro(&#39;onlyTrashed&#39;, function (Builder $builder) { $model = $builder-&gt;getModel(); $builder-&gt;withoutGlobalScope($this)-&gt;where( $model-&gt;getQualifiedDeletedAtColumn(), &#39;&lt;&gt;&#39;, 0 ); return $builder; }); } } SoftDeletingScope \u7684\u4f5c\u7528\uff0c\u662f\u5728\u6a21\u578b\u7684\u67e5\u8be2\u5185\u52a0\u5165\u300c\u672a\u5220\u9664\u300d\u6216\u300c\u5df2\u5220\u9664\u300d\u7b49\u7279\u5b9a\u6761\u4ef6\uff0c\u8be6\u60c5\u53ef\u53c2\u8003 \u5b98\u65b9\u6587\u6863\u3002\n Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints. - Laravel 5.7 Documentation\n \u53e6\u5916\uff0c\u8fd9\u91cc\u6211\u5e76\u6ca1\u6709\u7ee7\u627f Eloquent \u7684 SoftDeletingScope\uff0c\u539f\u56e0\u6709\u4e09\uff1a\n \u539f\u4ee3\u7801\u6539\u52a8\u4e0d\u65b9\u4fbf\uff0c\u51e0\u4e4e\u6240\u6709\u65b9\u6cd5\u90fd\u9700\u8981\u8986\u76d6\u91cd\u5199\u3002 \u9879\u76ee\u540e\u671f\u5347\u7ea7\u6846\u67b6\u7248\u672c\uff0c\u4e0d\u5e0c\u671b\u6846\u67b6\u4ee3\u7801\u7684\u6539\u52a8\u5f71\u54cd\u6b64\u5904\u3002 \u6839\u636e\u5b98\u65b9\u6587\u6863\u5bf9\u4e8e Global Scope \u7684\u89e3\u91ca\uff0c\u8f6f\u5220\u9664\u5373\u662f\u5229\u7528\u5b83\u5b9e\u73b0\u3002\u6240\u4ee5\u5b9e\u9645\u4e0a Scope \u662f\u4e00\u9879\u660e\u786e\u5f00\u653e\u7684\u7279\u6027\uff1b\u4f60\u53ef\u4ee5\u60f3\u8c61\u4e3a\u6211\u4eec\u6b63\u5728\u5229\u7528 Scope \u81ea\u884c\u5b9e\u73b0\u8f6f\u5220\u9664\u3002  0x04 SoftDeletes Trait \u65b0\u5efa\u4e00\u4e2a Trait\uff0c\u4ee3\u7801\u6bd4\u8f83\u957f\uff0c\u5982\u4e0b\u3002\nnamespace App\\Traits; use App\\Scopes\\MySoftDeletingScope; use Illuminate\\Database\\Eloquent\\SoftDeletes; trait MySoftDeletes { use SoftDeletes; \/** * Boot the soft deleting trait for a model. * * @return void *\/ public static function bootSoftDeletes() { static::addGlobalScope(new MySoftDeletingScope()); } \/** * Perform the actual delete query on this model instance. * * @return void *\/ protected function runSoftDelete() { $query = $this-&gt;newModelQuery()-&gt;where($this-&gt;getKeyName(), $this-&gt;getKey()); $time = $this-&gt;freshTimestamp(); $columns = [$this-&gt;getDeletedAtColumn() =&gt; $time-&gt;timestamp]; $this-&gt;{$this-&gt;getDeletedAtColumn()} = $time; if ($query-&gt;update($columns)) { $this-&gt;syncOriginal(); } } \/** * Restore a soft-deleted model instance. * * @return bool|null *\/ public function restore() { \/\/ If the restoring event does not return false, we will proceed with this  \/\/ restore operation. Otherwise, we bail out so the developer will stop  \/\/ the restore totally. We will clear the deleted timestamp and save.  if ($this-&gt;fireModelEvent(&#39;restoring&#39;) === false) { return false; } $this-&gt;{$this-&gt;getDeletedAtColumn()} = 0; \/\/ Once we have saved the model, we will fire the &#34;restored&#34; event so this  \/\/ developer will do anything they need to after a restore operation is  \/\/ totally finished. Then we will return the result of the save call.  $this-&gt;exists = true; $result = $this-&gt;save(); $this-&gt;fireModelEvent(&#39;restored&#39;, false); return $result; } \/** * Determine if the model instance has been soft-deleted. * * @return bool *\/ public function trashed() { return $this-&gt;{$this-&gt;getDeletedAtColumn()} != 0; } } SoftDeletes \u7684\u4f5c\u7528\u662f\u8d4b\u4e88\u6a21\u578b\u67e5\u8be2\u65f6\uff0c\u4f7f\u7528\u66f4\u52a0\u8bed\u4e49\u5316\u547d\u540d\u7684\u65b9\u6cd5\uff0c\u67e5\u8be2\u300c\u672a\u5220\u9664\u300d\u3001\u300c\u5df2\u5220\u9664\u300d\u7b49\u7279\u5b9a\u6761\u4ef6\u7684\u6a21\u578b\uff1b\u540c\u65f6\uff0c\u5728 bootSoftDeletes \u65b9\u6cd5\u5185\uff0c\u6302\u8f7d\u4e0a\u4e00\u6b65\u5b9a\u4e49\u7684 Global Scope\u3002\n\u6ce8\u610f\uff1aTrait \u4e0d\u53ef\u4ee5\u7ee7\u627f\uff0c\u4f46\u53ef\u4ee5\u5d4c\u5957\u3001\u8986\u76d6\u3002\u6240\u4ee5\u6b64\u5904\u6211 use SoftDeletes\uff0c\u5e76\u91cd\u5199\u5176\u4e2d\u90e8\u5206\u65b9\u6cd5\u5b9e\u73b0\u3002\n0x05 Surprise&hellip; Check list \u7684\u6700\u540e\u4e00\u6761\uff0cLaravel \u7ed9\u6211\u4eec\u7559\u4e86\u4e2a\u60ca\u559c\u3002\nSoftDelete \u7279\u6027\u5e76\u4e0d\u662f\u5b8c\u5168\u89e3\u8026\u7684\u3002\u9664\u4e86\u521a\u521a\u51e0\u5904\u975e\u5e38\u660e\u663e\u9700\u8981\u4fee\u6539\u7684\u5730\u65b9\u4e4b\u5916\uff0c\u8fd8\u6709\u4e00\u5904\u9690\u85cf\u5f88\u6df1\u7684\u6697\u5751\u3002\n\u4eca\u5929\u5728\u4f7f\u7528 HasManyThrough \u65f6\uff0c\u53d1\u73b0\u4e00\u4e2a\u5947\u8469\u95ee\u9898\uff0c\u67e5\u8be2\u7684 SQL \u7ecf\u8fc7\u8c03\u8bd5\u8f93\u51fa\uff0c\u53d1\u73b0\u4f9d\u7136\u6709 IS NULL \u7684\u67e5\u8be2\u6761\u4ef6\u3002\n\u7ecf\u8fc7\u4e00\u756a\u6392\u67e5\uff0c\u53d1\u73b0\u5728 Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough \u5185\u6709\u4e00\u65b9\u6cd5 throughParentSoftDeletes \ud83e\udd14\u3002\n\u53c8\u6709\u4e24\u65b9\u6cd5 performJoin\u3001getRelationExistenceQueryForSelfRelation \u5229\u7528\u5982\u4e0a\u65b9\u6cd5\uff0c\u5224\u65ad\u6a21\u578b\u662f\u5426 use SoftDeletes\uff1b\u82e5\u5df2 use\uff0c\u5219 whereNull\u3002\n\u597d\u6c14\u554a\uff01\n\u4e8e\u662f\uff0c\u4f60\u8fd8\u9700\u8981\u8fdb\u884c\u4e24\u6b65\u3002\n  \u5728\u6a21\u578b\u5185\uff08\u6216\u8005\u4f60\u53ef\u4ee5\u521b\u5efa\u4e2a\u516c\u5171\u57fa\u7c7b\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u5199\u5728\u5355\u72ec\u7684 Trait \u4e2d\uff09\u91cd\u5199 newHasManyThrough \u65b9\u6cd5\uff0c\u521b\u5efa\u81ea\u5b9a\u4e49\u7684\u6a21\u578b\u5173\u7cfb\u7c7b\u3002\nprotected function newHasManyThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey) { return new MyHasManyThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey); }   \u65b0\u5efa\u5982\u4e0a MyHasManyThrough \u7c7b\uff0c\u91cd\u5199\u90a3\u4e24\u4e2a\u5751\u7239\u7684\u65b9\u6cd5\uff0c\u66ff\u6362 whereNull\u3002\nuse Illuminate\\Database\\Eloquent\\Builder; use Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough; class MyHasManyThrough extends HasManyThrough { protected function performJoin(Builder $query = null) { $query = $query ?: $this-&gt;query; $farKey = $this-&gt;getQualifiedFarKeyName(); $query-&gt;join($this-&gt;throughParent-&gt;getTable(), $this-&gt;getQualifiedParentKeyName(), &#39;=&#39;, $farKey); if ($this-&gt;throughParentSoftDeletes()) { $query-&gt;where($this-&gt;throughParent-&gt;getQualifiedDeletedAtColumn(), &#39;=&#39;, 0); } } public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = [&#39;*&#39;]) { $query-&gt;from($query-&gt;getModel()-&gt;getTable().&#39; as &#39;.$hash = $this-&gt;getRelationCountHash()); $query-&gt;join($this-&gt;throughParent-&gt;getTable(), $this-&gt;getQualifiedParentKeyName(), &#39;=&#39;, $hash.&#39;.&#39;.$this-&gt;secondLocalKey); if ($this-&gt;throughParentSoftDeletes()) { $query-&gt;where($this-&gt;throughParent-&gt;getQualifiedDeletedAtColumn(), &#39;=&#39;, 0); } $query-&gt;getModel()-&gt;setTable($hash); return $query-&gt;select($columns)-&gt;whereColumn( $parentQuery-&gt;getQuery()-&gt;from.&#39;.&#39;.$this-&gt;localKey, &#39;=&#39;, $this-&gt;getQualifiedFirstKeyName() ); } }   0xFF \u611f\u60f3 \u7ec8\u4e8e\uff0c\u5728\u4fee\u6539\u8fd9\u4e48\u591a\u7c7b\u4e4b\u540e\uff0c\u6211\u4eec\u5b9e\u73b0\u4e86\u7528\u6574\u578b\u65f6\u95f4\u6233\u4ee3\u66ff DATETIME + NULL \u5b9e\u73b0\u8f6f\u5220\u9664\u3002\n\u82e5\u540e\u671f\u53d1\u73b0\u6709\u5176\u5b83\u7684\u5751\uff0c\u586b\u6ee1\u518d\u7ee7\u7eed\u56de\u6765\u8865\u5145\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-model-override-soft-delete\/","summary":"0x00 \u80cc\u666f Laravel \u81ea\u5e26\u8f6f\u5220\u9664\u4f7f\u7528\u7279\u6b8a\u503c NULL \u8868\u793a\u6b64\u8bb0\u5f55\u672a\u88ab\u5220\u9664\u3002\u7531\u6b64\u5f15\u51fa\u4e00\u4e2a\u95ee\u9898\u3002\n\u8bbe\u60f3\uff0c\u67d0\u8868\u5185\u9700\u8981\u5efa\u7acb\u7d22\u5f15\uff0c\u7d22\u5f15\u5b57\u6bb5\u4e3a name, deleted_at\u3002\n\u5047\u8bbe\u6b64\u7d22\u5f15\u6761\u4ef6\u5fc5\u5b9a\u552f\u4e00\uff0c\u53ef\u5efa\u7acb Uniuqe \u7d22\u5f15\u3002\u7136\u800c deleted_at \u5141\u8bb8 NULL \u5b58\u5728\uff0c\u5bfc\u81f4\u7d22\u5f15\u65e0\u6548\uff0c\u5728\u67e5\u8be2\u65f6\u964d\u7ea7\u4e3a Index\u3002\n\u56e0\u6b64\uff0c\u5728\u7edd\u5927\u591a\u6570\u573a\u666f\u4e0b\uff0c\u6211\u4eec\u67e5\u8be2\u672a\u88ab\u5220\u9664\uff08deleted_at IS NULL\uff09\u7684\u6570\u636e\uff0c\u552f\u4e00\u7d22\u5f15\u90fd\u6ca1\u6709\u5375\u7528\u3002","title":"Laravel 5.7 \u91cd\u5199\u8f6f\u5220\u9664\u5b57\u6bb5\u4e3a\u65f6\u95f4\u6233"},{"content":"\u6700\u8fd1\u53d1\u73b0\u4e2a\u95ee\u9898\uff0c\u8def\u7531\u5668\u6302\u4e86 SS \u4f46\u662f\u624b\u673a\u8bbf\u95ee Google Play \u4f9d\u65e7\u62a5\u9519\uff1a\n \u4ece\u670d\u52a1\u5668\u68c0\u7d22\u4fe1\u606f\u65f6\u51fa\u9519\u3002[DF-DFERH-01]\u3002\n \u9042\u6392\u67e5\uff0c\u53d1\u73b0\u662f\u7531\u4e8e\u56fd\u5185\u7248\u672c\u7684 Google Play \u5546\u5e97\u662f\u4f7f\u7528 services.googleapis.cn \u57df\u540d\uff0c\u800c .cn \u57df\u9ed8\u8ba4\u76f4\u8fde\u56fd\u5185 DNS \u8fdb\u884c\u89e3\u6790\uff0c\u800c GFW \u53c8\u7ed9\u8fd9\u4e2a\u57df\u540d\u4e0b\u6bd2\u5bfc\u81f4 DNS \u6c61\u67d3\uff0c\u65e0\u6cd5\u8bbf\u95ee\u3002\n\u4e8e\u662f\u4e09\u79cd\u65b9\u6848\u3002\n \u4f7f\u7528\u5e72\u51c0\u7684 DNS \u89e3\u6790\u51fa\u771f\u5b9e\u7684 IP \u5199\u5165\u8bbe\u5907 Hosts \u6216\u8005 Dnsmasq \u7684\u914d\u7f6e\u3002 \u6e05\u9664 DNS \u7f13\u5b58\u540e\uff0c\u5f3a\u5236\u8d70\u4ee3\u7406\u8f6c\u53d1 DNS \u8bf7\u6c42\uff0c\u7136\u540e\u6253\u5f00 Google Play\u3002 \u76f4\u63a5\u4f7f\u7528 SS \u8f6c\u53d1\u6240\u6709 DNS \u8bf7\u6c42\uff0c\u4e0d\u76f4\u8fde DNS\u3002  \u6700\u7ec8\u6211\u91c7\u7528\u7b2c\u4e00\u79cd\u65b9\u6848\u89e3\u51b3\uff0c\u76ee\u524d\u6211\u89e3\u6790\u51fa\u6765\u6b64\u57df\u540d IP \u4e3a 216.58.197.195\uff0c\u4fee\u6539 dnsmasq.conf \u8ffd\u52a0\u5982\u4e0b\u884c\u5373\u53ef\u3002\naddress=\/services.googleapis.cn\/216.58.197.195 ","permalink":"https:\/\/wi1dcard.dev\/posts\/google-play-dns-poisoning-in-china\/","summary":"\u6700\u8fd1\u53d1\u73b0\u4e2a\u95ee\u9898\uff0c\u8def\u7531\u5668\u6302\u4e86 SS \u4f46\u662f\u624b\u673a\u8bbf\u95ee Google Play \u4f9d\u65e7\u62a5\u9519\uff1a\n \u4ece\u670d\u52a1\u5668\u68c0\u7d22\u4fe1\u606f\u65f6\u51fa\u9519\u3002[DF-DFERH-01]\u3002\n \u9042\u6392\u67e5\uff0c\u53d1\u73b0\u662f\u7531\u4e8e\u56fd\u5185\u7248\u672c\u7684 Google Play \u5546\u5e97\u662f\u4f7f\u7528 services.googleapis.cn \u57df\u540d\uff0c\u800c .cn \u57df\u9ed8\u8ba4\u76f4\u8fde\u56fd\u5185 DNS \u8fdb\u884c\u89e3\u6790\uff0c\u800c GFW \u53c8\u7ed9\u8fd9\u4e2a\u57df\u540d\u4e0b\u6bd2\u5bfc\u81f4 DNS \u6c61\u67d3\uff0c\u65e0\u6cd5\u8bbf\u95ee\u3002","title":"\u89e3\u51b3 Google Play \u79d1\u5b66\u4e0a\u7f51\u4f9d\u65e7\u65e0\u6cd5\u8bbf\u95ee"},{"content":"Laravel 5.7 \u4e8e\u524d\u51e0\u5929\u53d1\u5e03\uff0c\u8feb\u4e0d\u53ca\u5f85\u7ed9\u6b63\u5728\u5f00\u53d1\u7684\u65b0\u9879\u76ee\u505a\u4e86\u5347\u7ea7\u3002\n\u5728\u6b64\u6574\u7406\u4e00\u4e0b\u6a21\u578b\u5e38\u7528\u5c5e\u6027\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u8be2\u3002\n$fillable = [ &#39;\u53ef\u6279\u91cf\u586b\u5145\u7684\u5b57\u6bb5&#39; ]; $guarded = [ &#39;\u4e0e\u4e0a\u76f8\u53cd&#39; ]; $hidden = [ &#39;\u6a21\u578b\u8f6c\u6362\u4e3a\u6570\u7ec4\u65f6\u5e94\u5f53\u9690\u85cf\u7684\u5b57\u6bb5&#39; ]; $visable = [ &#39;\u4e0e\u4e0a\u76f8\u53cd&#39; ]; $appends = [ &#39;\u6a21\u578b\u8f6c\u6362\u4e3a\u6570\u7ec4\u65f6\u5e94\u5f53\u8ffd\u52a0\u7684\u865a\u62df\u5b57\u6bb5&#39; \/\/ \u4f8b\u5982\u8bbf\u95ee\u5668 ]; $with = [ &#39;\u5e94\u5f53\u9884\u52a0\u8f7d\u7684\u5173\u8054\u5173\u7cfb&#39;, ]; $attributes = [ &#39;\u5b57\u6bb5\u540d&#39; =&gt; &#39;\u5b57\u6bb5\u9ed8\u8ba4\u503c&#39; ]; $casts = [ &#39;\u5b57\u6bb5\u540d&#39; =&gt; &#39;\u81ea\u52a8\u7c7b\u578b\u8f6c\u6362\u7684\u76ee\u6807\u7c7b\u578b&#39; ]; $dates = [ &#39;\u5e94\u5f53\u88ab\u8f6c\u6362\u4e3a\u65e5\u671f\u65f6\u95f4\u7684\u5b57\u6bb5&#39; ]; $touches = [ &#39;\u6a21\u578b\u66f4\u65b0\u65f6\u5e94\u5f53\u4e00\u5e76\u66f4\u65b0\u7684\u5173\u8054\u5173\u7cfb&#39; ]; \/\/ \u4ee5\u4e0b\u4e3a\u6269\u5c55\u5305\u4f7f\u7528\u7684\u5c5e\u6027  \/\/ https:\/\/github.com\/dwightwatson\/validating $rules = [ &#39;\u5b57\u6bb5&#39; =&gt; &#39;\u6a21\u578b\u81ea\u8eab\u9a8c\u8bc1\u89c4\u5219&#39; ]; \/\/ https:\/\/github.com\/Askedio\/laravel-soft-cascade $softCascade = [ &#39;\u8f6f\u5220\u9664\u65f6\u4e00\u5e76\u5220\u9664\u7684\u5173\u8054&#39; ]; \/\/ https:\/\/github.com\/spatie\/eloquent-sortable $sortable = [ &#39;order_column_name&#39; =&gt; &#39;order_column&#39;, &#39;sort_when_creating&#39; =&gt; true, ]; \/\/ https:\/\/github.com\/nicolaslopezj\/searchable $searchable = [ &#39;columns&#39; =&gt; [], &#39;joins&#39; =&gt; [], ]; ","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-eloquent-model-properties\/","summary":"Laravel 5.7 \u4e8e\u524d\u51e0\u5929\u53d1\u5e03\uff0c\u8feb\u4e0d\u53ca\u5f85\u7ed9\u6b63\u5728\u5f00\u53d1\u7684\u65b0\u9879\u76ee\u505a\u4e86\u5347\u7ea7\u3002\n\u5728\u6b64\u6574\u7406\u4e00\u4e0b\u6a21\u578b\u5e38\u7528\u5c5e\u6027\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u8be2\u3002\n$fillable = [ &#39;\u53ef\u6279\u91cf\u586b\u5145\u7684\u5b57\u6bb5&#39; ]; $guarded = [ &#39;\u4e0e\u4e0a\u76f8\u53cd&#39; ]; $hidden = [ &#39;\u6a21\u578b\u8f6c\u6362\u4e3a\u6570\u7ec4\u65f6\u5e94\u5f53\u9690\u85cf\u7684\u5b57\u6bb5&#39; ]; $visable = [ &#39;\u4e0e\u4e0a\u76f8\u53cd&#39; ]; $appends = [ &#39;\u6a21\u578b\u8f6c\u6362\u4e3a\u6570\u7ec4\u65f6\u5e94\u5f53\u8ffd\u52a0\u7684\u865a\u62df\u5b57\u6bb5&#39; \/\/ \u4f8b\u5982\u8bbf\u95ee\u5668 ]; $with = [ &#39;\u5e94\u5f53\u9884\u52a0\u8f7d\u7684\u5173\u8054\u5173\u7cfb&#39;, ]; $attributes = [ &#39;\u5b57\u6bb5\u540d&#39; =&gt; &#39;\u5b57\u6bb5\u9ed8\u8ba4\u503c&#39; ]; $casts = [ &#39;\u5b57\u6bb5\u540d&#39; =&gt; &#39;\u81ea\u52a8\u7c7b\u578b\u8f6c\u6362\u7684\u76ee\u6807\u7c7b\u578b&#39; ]; $dates = [ &#39;\u5e94\u5f53\u88ab\u8f6c\u6362\u4e3a\u65e5\u671f\u65f6\u95f4\u7684\u5b57\u6bb5&#39; ]; $touches = [ &#39;\u6a21\u578b\u66f4\u65b0\u65f6\u5e94\u5f53\u4e00\u5e76\u66f4\u65b0\u7684\u5173\u8054\u5173\u7cfb&#39; ]; \/\/ \u4ee5\u4e0b\u4e3a\u6269\u5c55\u5305\u4f7f\u7528\u7684\u5c5e\u6027  \/\/ https:\/\/github.","title":"Laravel 5.7 \u6a21\u578b\u5e38\u7528\u5c5e\u6027\u96c6\u5408"},{"content":" How to push commits and tags in git using the same command&hellip;\n \u8fd1\u671f\u7ef4\u62a4\u9879\u76ee\uff0c\u6709\u4e24\u4e2a\u8fdc\u7a0b\u4ed3\u5e93\uff0c\u6bcf\u6b21\u53d1\u5e03\u7248\u672c\u9700\u8981\u6267\u884c\u56db\u6761\u547d\u4ee4\u3002\ngit push first git push first --tags git push second git push second --tags \u771f\u8981\u547d\u3002\n\u7ecf\u67e5\u8be2\u53d1\u73b0 Git \u4f3c\u4e4e\u6682\u65f6\u6ca1\u6709\u547d\u4ee4\u89e3\u51b3\u6b64\u573a\u666f\uff0c\u6216\u8bb8\u662f\u6015\u5f15\u8d77\u6b67\u4e49\u548c\u6df7\u6dc6\u5427\u3002\n\u4e0d\u8fc7\u6709\u4e2a\u65c1\u95e8\u5de6\u9053\uff0c\u5229\u7528 Git \u547d\u4ee4\u522b\u540d\u5b9e\u73b0\u3002\ngit config --global alias.p &#39;!git push &amp;&amp; git push --tags&#39; # or # git config --global alias.pa &#39;!git push --all &amp;&amp; git push --tags&#39; \u7136\u540e\u5c31\u53ef\u4ee5\u7528\uff1a\ngit p # or # git pa \u4e00\u6761\u547d\u4ee4\u641e\u5b9a\u5566\u3002\n\u53c2\u8003\uff1ahttps:\/\/stackoverflow.com\/questions\/19404436\/git-push-and-git-push-tags-in-the-same-command\n","permalink":"https:\/\/wi1dcard.dev\/posts\/git-push-with-tags\/","summary":"How to push commits and tags in git using the same command&hellip;\n \u8fd1\u671f\u7ef4\u62a4\u9879\u76ee\uff0c\u6709\u4e24\u4e2a\u8fdc\u7a0b\u4ed3\u5e93\uff0c\u6bcf\u6b21\u53d1\u5e03\u7248\u672c\u9700\u8981\u6267\u884c\u56db\u6761\u547d\u4ee4\u3002\ngit push first git push first --tags git push second git push second --tags \u771f\u8981\u547d\u3002","title":"Git \u4e00\u6b21\u6027\u63a8\u9001\u63d0\u4ea4\u548c\u6807\u7b7e"},{"content":"\u8bba\u5982\u4f55\u4ee5\u7a0b\u5e8f\u5458\u7684\u65b9\u5f0f\uff0c\u8f7b\u91cf\u3001\u5feb\u901f\u3001\u4f18\u96c5\u5730\u8f6c\u6362 SVG \u5230 PNG\u3002\n0x00 \u95ee\u9898\u63cf\u8ff0 \u8fd1\u671f\u516c\u53f8\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 Navicat \u5236\u4f5c E-R \u56fe\uff0c\u4e3a\u4e86\u5feb\u901f\u8fdb\u884c\u5934\u8111\u98ce\u66b4\uff0c\u9700\u8981\u628a\u5173\u7cfb\u56fe\u6253\u5370\u51fa\u6765\u3002\n\u7531\u4e8e\u4e1a\u52a1\u903b\u8f91\u6bd4\u8f83\u590d\u6742\uff0c\u56fe\u7247\u4e5f\u8d8a\u6765\u8d8a\u5e9e\u5927\u3002\n\u6700\u65e9\u5c1d\u8bd5\u4f7f\u7528 File -&gt; Print as... -&gt; PNG \u5bfc\u51fa\uff0c\u4f46\u662f\u540e\u6765\u53d1\u73b0\u5176 DPI \u6bd4\u8f83\u4f4e\uff0c\u800c\u4e14\u5728\u6a21\u578b\u5173\u7cfb\u6bd4\u8f83\u5927\u7684\u65f6\u5019\uff0c\u5bfc\u51fa\u7684 PNG \u4f1a\u6bd4\u8f83\u6a21\u7cca\u3002\n\u540e\u5c1d\u8bd5\u5bfc\u51fa\u81f3 PDF\uff0c\u4f46\u662f Page setup \u6700\u591a\u53ea\u80fd\u8bbe\u7f6e A0 \u5927\u5c0f\uff0c\u8fd9\u6837\u5bfc\u51fa\u7684 PDF \u5c31\u4f1a\u88ab\u5206\u5272\u4e3a\u4e24\u9875\uff0c\u8fd8\u9700\u8981\u9ebb\u70e6 UI \u5c0f\u59d0\u59d0\u5408\u5e76\u3002\n\u6700\u540e\u8fd8\u5269\u7ec8\u6781\u65b9\u6848\uff0c\u5c31\u662f SVG\uff0c\u5f88\u4e0d\u5e78\u7684\u662f\u6253\u5370\u5e97\u7684\u7535\u8111\u6ca1\u6709 macOS \u7684\u5b57\u4f53\uff0c\u800c\u4e14\u5f88\u5361\u5f88\u5361\u3002\n\u7531\u6b64\uff0c\u95ee\u9898\u88ab\u8f6c\u5316\u4e3a\uff1aSVG =&gt; PNG\u3002\n\u65b9\u6848\u5176\u5b9e\u6709\u5f88\u591a\uff0c\u8c37\u6b4c\u4e00\u5927\u628a\u3002\u7b80\u5355\u5217\u4e3e\u51e0\u4e2a\u3002\n \u5728\u7ebf\u8f6c\u6362\u3002 AI Command + Shift + 3 \u622a\u56fe\u3002 Safari \/ Chrome \u6253\u5f00\u518d\u5bfc\u51fa\u4e3a\u56fe\u7247\u3002 qlmanage inkscape ImageMagick &hellip;  \u4f46\u90fd\u4e0d\u592a\u7b26\u5408\u6211\u7684\u9700\u6c42\u3002\n \u6240\u8c13\u8f7b\u91cf\uff0cAI \u5c31\u7b97\u4e86\uff0c\u6211\u53ef\u4e0d\u662f UI \u5927\u4f6c\u3002 \u6240\u8c13\u5feb\u901f\uff0c\u88c5\u4e00\u5927\u5806 Casks \u4e5f\u7b97\u4e86\u5427\u3002 \u6240\u8c13\u4f18\u96c5\uff0c\u900f\u660e\u3001DPI \u9009\u9879\u4e5f\u4e0d\u80fd\u7f3a\u3002  \u8003\u8651\u5230\u516c\u53f8\u9879\u76ee\u4fdd\u5bc6\u6027\uff0c\u5728\u7ebf\u8f6c\u6362\u4e5f\u88ab Pass\u3002\n0x01 Coder&rsquo;s Way \u65e2\u7136\u4f5c\u4e3a\u7a0b\u5e8f\u5458\u540c\u65f6\u53c8\u662f\u4e2a\u61d2\u86cb\uff0c\u90a3\u5c31\u8981\u7528\u61d2\u4eba + \u7a0b\u5e8f\u5458\u7684\u65b9\u5f0f\u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002\n\u7ecf\u8fc7\u4e00\u756a\u5c1d\u8bd5\uff0c\u6700\u5408\u9002\u7684\u65b9\u6848\u662f librsvg\u3002\u4e00\u884c\u547d\u4ee4\u641e\u5b9a\u3002\nImageMagick \u4e5f\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\uff0c\u4f46\u5176\u5185\u90e8\u7684 SVG Render \u5f15\u64ce\u4f3c\u4e4e\u652f\u6301\u4e0d\u5b8c\u5168\uff0c\u8f6c\u6362\u65f6\u51fa\u73b0\u62a5\u9519\uff0cGitHub Issue\uff1b\u6211\u7684\u7248\u672c\u662f 7.0.8-11\uff0c\u82e5\u6709\u54ea\u4f4d\u5927\u4f6c\u4e86\u89e3\u60c5\u51b5\u6b22\u8fce\u7559\u8a00\u8ba8\u8bba\uff0c\u8c22\u8c22\u3002\n0x02 \u5b89\u88c5 brew install librsvg 0x03 \u4f7f\u7528 rsvg-convert --help \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u53c2\u6570\u770b\u8d77\u6765\u4e5f\u4e0d\u600e\u4e48\u9ad8\u6df1\uff0c\u4f3c\u4e4e\u5f88\u9002\u5408\u4e0d\u719f\u6089\u56fe\u50cf\u5904\u7406\u9886\u57df\u7684\u7a0b\u5e8f\u5458\u4eec\u3002\nrsvg-convert -d 180 -p 180 test.svg &gt; test.png \u8fd9\u91cc\u6211\u589e\u5927\u4e00\u500d DPI\uff0c\u8ba9\u56fe\u7247\u770b\u8d77\u6765\u5f88\u6e05\u6670\u3002\u8f6c\u6362\u901f\u5ea6\u5f88\u5feb\uff0c\u5b9e\u6d4b 11800\u2006\u00d7\u200612698 \u7684\u56fe\u7247\u5728\u6211\u7684\u83dc\u9e21 MacBook \u4e0a\u53ea\u9700\u8981\u4e09\u79d2\u5de6\u53f3\u3002\n0xFF \u7ed3\u8bed \u771f\u5b9e\u6253\u5370\u51fa\u6765\u7684 E-R \u56fe\u8db3\u8db3\u6709\u4e00\u9762\u5899\u90a3\u4e48\u5927&hellip; \u53ef\u6015\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-convert-svg-to-png\/","summary":"\u8bba\u5982\u4f55\u4ee5\u7a0b\u5e8f\u5458\u7684\u65b9\u5f0f\uff0c\u8f7b\u91cf\u3001\u5feb\u901f\u3001\u4f18\u96c5\u5730\u8f6c\u6362 SVG \u5230 PNG\u3002\n0x00 \u95ee\u9898\u63cf\u8ff0 \u8fd1\u671f\u516c\u53f8\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 Navicat \u5236\u4f5c E-R \u56fe\uff0c\u4e3a\u4e86\u5feb\u901f\u8fdb\u884c\u5934\u8111\u98ce\u66b4\uff0c\u9700\u8981\u628a\u5173\u7cfb\u56fe\u6253\u5370\u51fa\u6765\u3002\n\u7531\u4e8e\u4e1a\u52a1\u903b\u8f91\u6bd4\u8f83\u590d\u6742\uff0c\u56fe\u7247\u4e5f\u8d8a\u6765\u8d8a\u5e9e\u5927\u3002\n\u6700\u65e9\u5c1d\u8bd5\u4f7f\u7528 File -&gt; Print as... -&gt; PNG \u5bfc\u51fa\uff0c\u4f46\u662f\u540e\u6765\u53d1\u73b0\u5176 DPI \u6bd4\u8f83\u4f4e\uff0c\u800c\u4e14\u5728\u6a21\u578b\u5173\u7cfb\u6bd4\u8f83\u5927\u7684\u65f6\u5019\uff0c\u5bfc\u51fa\u7684 PNG \u4f1a\u6bd4\u8f83\u6a21\u7cca\u3002","title":"macOS \u8f6c\u6362 SVG \u5230 PNG"},{"content":"GitHub \u539f\u4ed3\u5e93\u7684 Commit \u8bb0\u5f55\u5df2\u7ecf\u6d88\u5931\uff0cIssue \u529f\u80fd\u4e5f\u88ab\u5173\u95ed\u4e86\u3002\n\u73b0\u79fb\u52a8\u5230 https:\/\/github.com\/hq450\/fancyss\u3002\n\u4f3c\u4e4e\uff0c\u4e5f\u662f\u88ab\u8bf7\u53bb\u559d\u8336\u4e86\uff1f\n\u67d0\u4e9b\u4eba\uff0c\u5e72\u561b\u975e\u8981\u5c01\u4eba\u5634\u5df4\u5462\u3002\u63a9\u8033\u76d7\u94c3\uff0c\u53ef\u7b11\u3002\n\u66f4\u53ef\u7b11\u7684\u662f\uff0c\u591a\u6570\u4eba\u4e0d\u89c9\u5f97\u81ea\u5df1\u88ab\u5c01\u4f4f\u5634\u5df4\u3002\n\u4e60\u60ef\u4e86\u4e0d\u8bf4\u8bdd\u7684\u65e5\u5b50\uff0c\u4e60\u60ef\u4e86\u7528\u539f\u59cb\u4eba\u7684\u65b9\u5f0f\u3002\n\u6700\u53ef\u6015\u7684\u6c38\u8fdc\u662f\u4eba\u7684\u601d\u7ef4\u3002\n\u4e0d\u591a\u8bf4\u4e86\u3002\n\u6211\u7684 RT-AC86U Koolshare Merlin Shadowsocks 1.3.6 \u60f3\u8981\u5347\u7ea7\u65f6\u51fa\u73b0 404\uff0c\u65e0\u6cd5\u6b63\u5e38\u5728\u7ebf\u5347\u7ea7\u3002\n\u7ecf\u67e5\u8bc1\u662f\u5982\u4e0a\u6240\u8ff0\u60c5\u51b5\u3002\n\u89e3\u51b3\u65b9\u6848\u6bd4\u8f83\u7b80\u5355\uff0c\u4fee\u6539 \/jffs\/.koolshare\/scripts\/ss_update.sh \u66ff\u6362\u4ed3\u5e93\u5730\u5740\u5373\u53ef\u3002\n\u66ff\u6362\u524d\uff1a\nmain_url=&#34;https:\/\/raw.githubusercontent.com\/koolshare\/rogsoft\/master\/shadowsocks&#34; backup_url=&#34;https:\/\/rogsoft.ngrok.wang\/shadowsocks&#34; \u66ff\u6362\u540e\uff1a\nmain_url=&#34;https:\/\/raw.githubusercontent.com\/hq450\/fancyss\/master\/fancyss_hnd&#34; \u622a\u81f3\u76ee\u524d\uff0c\u5907\u7528\u4ed3\u5e93\u5730\u5740\u8fd8\u80fd\u7528\uff0c\u4f60\u4e5f\u53ef\u4ee5\u5148\u66ff\u6362\u4e3a\u5907\u7528\u5730\u5740\u5148\u5347\u7ea7\u5230\u8fc7\u6e21\u7248\u672c\u518d\u5347\u7ea7\u5230\u6700\u65b0\u7248\u3002\n\u7ee7\u7eed\u52a0\u6cb9\uff0c\u65e9\u65e5\u8089\u7ffb\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/merlin-koolshare-shadowsocks-transferred\/","summary":"GitHub \u539f\u4ed3\u5e93\u7684 Commit \u8bb0\u5f55\u5df2\u7ecf\u6d88\u5931\uff0cIssue \u529f\u80fd\u4e5f\u88ab\u5173\u95ed\u4e86\u3002\n\u73b0\u79fb\u52a8\u5230 https:\/\/github.com\/hq450\/fancyss\u3002\n\u4f3c\u4e4e\uff0c\u4e5f\u662f\u88ab\u8bf7\u53bb\u559d\u8336\u4e86\uff1f\n\u67d0\u4e9b\u4eba\uff0c\u5e72\u561b\u975e\u8981\u5c01\u4eba\u5634\u5df4\u5462\u3002\u63a9\u8033\u76d7\u94c3\uff0c\u53ef\u7b11\u3002\n\u66f4\u53ef\u7b11\u7684\u662f\uff0c\u591a\u6570\u4eba\u4e0d\u89c9\u5f97\u81ea\u5df1\u88ab\u5c01\u4f4f\u5634\u5df4\u3002\n\u4e60\u60ef\u4e86\u4e0d\u8bf4\u8bdd\u7684\u65e5\u5b50\uff0c\u4e60\u60ef\u4e86\u7528\u539f\u59cb\u4eba\u7684\u65b9\u5f0f\u3002\n\u6700\u53ef\u6015\u7684\u6c38\u8fdc\u662f\u4eba\u7684\u601d\u7ef4\u3002\n\u4e0d\u591a\u8bf4\u4e86\u3002\n\u6211\u7684 RT-AC86U Koolshare Merlin Shadowsocks 1.3.6 \u60f3\u8981\u5347\u7ea7\u65f6\u51fa\u73b0 404\uff0c\u65e0\u6cd5\u6b63\u5e38\u5728\u7ebf\u5347\u7ea7\u3002","title":"Koolshare \u6885\u6797\u56fa\u4ef6 Shadowsocks \u6613\u4e3b"},{"content":"\u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u5c55\u793a\u6548\u679c\u3002\nwechatapp-rebuild \u251c\u2500\u2500 components\/ \u251c\u2500\u2500 core\/ \u251c\u2500\u2500 images\/ \u251c\u2500\u2500 pages\/ \u251c\u2500\u2500 utils\/ \u251c\u2500\u2500 README.md \u251c\u2500\u2500 app.js \u251c\u2500\u2500 app.json \u251c\u2500\u2500 app.wxss \u2514\u2500\u2500 project.config.json 0x00 \u5b89\u88c5 macOS \u4f7f\u7528 tree \u547d\u4ee4\u9700\u8981\u5148\u8fdb\u884c\u5b89\u88c5\u3002\nbrew install tree 0x01 \u4f7f\u7528 \u4e00\u5982\u5176\u5b83\u547d\u4ee4\uff0c\u4f7f\u7528 tree --help \u53ef\u4ee5\u67e5\u770b\u5e2e\u52a9\u3002\n\u5b9e\u73b0\u5982\u4e0a\u6548\u679c\uff0c\u53ea\u9700\u8981\u8fd9\u6837\uff1a\ntree . -L 1 -F --dirsfirst 0x02 \u5206\u89e3  . \u53ef\u66ff\u6362\u4e3a\u4efb\u610f\u76ee\u5f55\uff0c\u5305\u62ec\u5f53\u524d\u76ee\u5f55\u4e0b\u7684\u5b50\u76ee\u5f55\uff0c\u4e5f\u53ef\u4ee5\u7701\u7565\u3002 -L * \u8868\u793a\u5c42\u7ea7\uff0c\u901a\u5e38\u53ea\u5c55\u793a\u9879\u76ee\u76ee\u5f55\u7ed3\u6784\u7b2c\u4e00\u5c42\u4fbf\u53ef\u3002 -F \u8868\u793a\u5728\u6587\u4ef6\u5939\u540e\u8ddf\u968f \/ \u659c\u7ebf\u3002 --dirsfirst \u8868\u793a\u6392\u5e8f\u65f6\u5c06\u6587\u4ef6\u5939\u59cb\u7ec8\u6392\u5728\u6587\u4ef6\u524d\u9762\u3002  0x03 \u7ed3\u8bed \u5229\u7528 awk \u8fd8\u53ef\u5b9e\u73b0\u81ea\u52a8\u8865\u5168\u6bcf\u884c\u7ed3\u5c3e\u7684\u7a7a\u683c\uff0c\u5e76\u8ffd\u52a0 \/\/ \u4ee5\u65b9\u4fbf\u7f16\u5199\u6ce8\u91ca\u3002\u6709\u5174\u8da3\u53ef\u81ea\u884c\u63a2\u7d22\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-tree-command\/","summary":"\u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u5c55\u793a\u6548\u679c\u3002\nwechatapp-rebuild \u251c\u2500\u2500 components\/ \u251c\u2500\u2500 core\/ \u251c\u2500\u2500 images\/ \u251c\u2500\u2500 pages\/ \u251c\u2500\u2500 utils\/ \u251c\u2500\u2500 README.md \u251c\u2500\u2500 app.js \u251c\u2500\u2500 app.json \u251c\u2500\u2500 app.wxss \u2514\u2500\u2500 project.","title":"macOS \u5229\u7528 tree \u547d\u4ee4\u5c55\u793a\u76ee\u5f55\u7ed3\u6784"},{"content":"\u4ece\u4e03\u6708\u4efd\u5f97\u77e5\u56fd\u5185\u955c\u50cf\u5f00\u59cb\u300c\u4f53\u68c0\u300d\u4e4b\u540e\uff0c\u4e00\u76f4\u6ca1\u6709\u6536\u5230\u6062\u590d\u7684\u6d88\u606f\u3002\n 2019 \u5e74 6 \u6708 4 \u65e5\u66f4\u65b0\uff1aLaravel-China \u955c\u50cf\u5c06\u4e8e\u4e24\u4e2a\u6708\u540e\u505c\u7528\uff0c\u53c2\u89c1\uff1ahttps:\/\/learnku.com\/articles\/30758\n \u76ee\u524d\uff0c\u5b98\u7f51\u4f9d\u65e7\u6302\u7740\u516c\u544a\uff1a\n \u901a\u77e5\uff1a7 \u6708 13 \u65e5\uff08\u5468\u4e94\uff09\u4e0b\u5348 5 \u70b9\u672c\u955c\u50cf\u5c06\u6682\u505c\u66f4\u65b0\uff0c\u5e76\u4e14\u5b89\u88c5\u5305\uff08zip\uff09\u8d44\u6e90\u7684\u4e0b\u8f7d\u5730\u5740\u5c06\u6307\u5411 GitHub\uff0c\u4e00\u76f4\u6301\u7eed\u5230 18 \u65e5\uff08\u4e0b\u5468\u4e09\uff09\u3002\u5c4a\u65f6\u672c\u955c\u50cf\u4ecd\u7136\u53ef\u4f7f\u7528\uff0c\u53ea\u662f\u4e0b\u8f7d\u5b89\u88c5\u5305\u65f6\u7531\u4e8e\u8d70\u56fd\u5916\u7684\u670d\u52a1\u5668\uff0c\u901f\u5ea6\u4f1a\u6bd4\u8f83\u6162\u3002\n\u539f\u56e0\uff1a\u6b64\u6b21\u6682\u505c\u671f\u95f4\u5c06\u5bf9\u672c\u955c\u50cf\u7f13\u5b58\u7684\u6240\u6709\u5b89\u88c5\u5305\uff08zip\uff09\u4ee5\u53ca\u5143\u6570\u636e\uff08json\uff09\u8fdb\u884c\u6821\u9a8c\u548c\u4fee\u590d\u3002\u4e0a\u6b21\u5168\u9762\u4f53\u68c0\u65f6\u95f4\u662f 2017 \u5e74 3 \u6708\u4efd\u3002\n\u30107 \u6708 18 \u65e5\u66f4\u65b0\u3011\uff1a\u7531\u4e8e\u955c\u50cf\u6682\u505c\u671f\u95f4\u6536\u5230\u4e00\u4e2a\u91cd\u8981\u7684 bug\uff0c\u6211\u4eec\u6b63\u5728\u8ffd\u8e2a\u5e76\u4fee\u590d\u6b64 bug\uff0c\u56e0\u6b64\u5c06\u955c\u50cf\u6062\u590d\u65f6\u95f4\u518d\u6b21\u5ef6\u957f\u4e00\u5468\uff0c\u5f88\u62b1\u6b49\u5404\u4f4d\uff0c\u8bf7\u518d\u8010\u5fc3\u7b49\u5f85\uff0c\u8c22\u8c22\uff01\u3002\n \u5c34\u5c2c\uff0c\u8fd9\u662f\u8981\u51c9\u51c9\u5417\u3002\n\u7531\u4e8e\u516c\u53f8\u670d\u52a1\u5668\u5728\u56fd\u5185\u963f\u91cc\u4e91\uff08\u6ca1\u529e\u6cd5\u6302 SS\uff09\uff0c\u90e8\u7f72\u9879\u76ee\u6267\u884c composer install \u7b80\u76f4\u7b49\u5230\u82b1\u90fd\u8c22\u4e86\uff0c\u4e0d\u7b26\u5408\u5e94\u6025\u60c5\u51b5\u9700\u8981\u5feb\u901f\u589e\u52a0\u5b9e\u4f8b\u7684\u9700\u6c42\uff0c\u7ecf\u8fc7\u4e00\u756a\u8c37\u6b4c\uff0c\u53d1\u73b0\u4e00\u66ff\u4ee3\u65b9\u6848\u3002\nhttps:\/\/packagist.laravel-china.org\/\n\u597d\u6b79\u4e5f\u662f\u51fa\u81ea\u5927\u540d\u9f0e\u9f0e\u7684 Laravel-China \u793e\u533a\uff0c\u5e94\u8be5\u80fd\u6297\u4e00\u9635\u5b50&hellip; \u5427\u3002\n\u5509\uff0c\u8fd8\u662f\u90a3\u53e5\u8bdd\uff0c\u52aa\u529b\u8d5a\u94b1\uff0c\u4e89\u53d6\u65e9\u65e5\u8089\u7ffb\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/packagist-mirror-in-china\/","summary":"<p>\u4ece\u4e03\u6708\u4efd\u5f97\u77e5\u56fd\u5185\u955c\u50cf\u5f00\u59cb\u300c\u4f53\u68c0\u300d\u4e4b\u540e\uff0c\u4e00\u76f4\u6ca1\u6709\u6536\u5230\u6062\u590d\u7684\u6d88\u606f\u3002<\/p>","title":"Packagist\uff08Composer\uff09\u4e2d\u56fd\u955c\u50cf"},{"content":"\u5927\u6982\u5728\u4e24\u4e2a\u6708\u4ee5\u524d\uff0c\u521a\u5165\u804c\u76ee\u524d\u6240\u5728\u7684\u516c\u53f8\uff0c\u8981\u6c42\u5199\u5468\u62a5\uff0c\u800c\u4e14\u8981\u6c42\u6bd4\u8f83\u8be6\u7ec6\uff0c\u6bcf\u5929\u7684\u4efb\u52a1\u90fd\u9700\u8981\u5217\u6e05\u695a\u3002\n\u5bf9\u4e8e\u6211\u8fd9\u79cd\u5f88\u5065\u5fd8\uff0c\u5e76\u4e14\u559c\u6b22\u4ee5\u7ed3\u679c\u4e3a\u5bfc\u5411\uff0c\u4e13\u6ce8\u4e8e\u4ee3\u7801\u7684\u7a0b\u5e8f\u5458\u7b80\u76f4\u8981\u547d\u3002\n\u6240\u4ee5\u4e0b\u51b3\u5fc3\uff0c\u641e\u4e2a\u5e2e\u6211\u5199\u5468\u62a5\u7684\u5de5\u5177\u3002\u4e8e\u662f\u8fd9\u4e2a\u9879\u76ee\u8bde\u751f\u4e86\u3002\n\u81ea\u5df1\u7528\u4e86\u4e00\u9635\u5b50\u611f\u89c9\u8fd8\u4e0d\u9519\uff0c\u7ecf\u8fc7\u4e00\u756a\u6574\u7406\u5b8c\u5584\u51b3\u5b9a\u5f00\u6e90\u3002\n\u4ed3\u5e93\u5730\u5740\uff1ahttps:\/\/github.com\/wi1dcard\/weekly-report\n\u5176\u5b9e\u6ca1\u4ec0\u4e48\u6280\u672f\u542b\u91cf\uff0c\u65e0\u975e\u5c31\u662f\u5229\u7528 Git \u7684\u63d0\u4ea4\u8bb0\u5f55\uff0c\u7f16\u6392\u6210 Markdown\u3002\nBTW\uff0c\u5176\u5b9e\u6216\u8bb8\u7528 Python \u5199\u4f1a\u66f4\u5408\u9002\u3002\n\u6700\u540e\uff0c\u6211\u7684\u5468\u62a5\u9879\u76ee VS Code \u914d\u7f6e\u5982\u4e0b\u3002\n{ &#34;[markdown]&#34;: { &#34;editor.wordWrap&#34;: &#34;off&#34;, &#34;editor.fontFamily&#34;: &#34;Inconsolata&#34;, &#34;editor.lineHeight&#34;: 24, &#34;editor.fontSize&#34;: 16, &#34;editor.fontWeight&#34;: &#34;normal&#34; }, &#34;markdown-pdf.displayHeaderFooter&#34;: false, &#34;markdown-pdf.includeDefaultStyles&#34;: false, &#34;markdown-pdf.styles&#34;: [ &#34;pdf.css&#34; ], &#34;markdown-pdf.width&#34;: &#34;30cm&#34;, &#34;markdown-pdf.height&#34;: &#34;100cm&#34; } ","permalink":"https:\/\/wi1dcard.dev\/posts\/weekly-report-toolkit\/","summary":"\u5927\u6982\u5728\u4e24\u4e2a\u6708\u4ee5\u524d\uff0c\u521a\u5165\u804c\u76ee\u524d\u6240\u5728\u7684\u516c\u53f8\uff0c\u8981\u6c42\u5199\u5468\u62a5\uff0c\u800c\u4e14\u8981\u6c42\u6bd4\u8f83\u8be6\u7ec6\uff0c\u6bcf\u5929\u7684\u4efb\u52a1\u90fd\u9700\u8981\u5217\u6e05\u695a\u3002\n\u5bf9\u4e8e\u6211\u8fd9\u79cd\u5f88\u5065\u5fd8\uff0c\u5e76\u4e14\u559c\u6b22\u4ee5\u7ed3\u679c\u4e3a\u5bfc\u5411\uff0c\u4e13\u6ce8\u4e8e\u4ee3\u7801\u7684\u7a0b\u5e8f\u5458\u7b80\u76f4\u8981\u547d\u3002\n\u6240\u4ee5\u4e0b\u51b3\u5fc3\uff0c\u641e\u4e2a\u5e2e\u6211\u5199\u5468\u62a5\u7684\u5de5\u5177\u3002\u4e8e\u662f\u8fd9\u4e2a\u9879\u76ee\u8bde\u751f\u4e86\u3002\n\u81ea\u5df1\u7528\u4e86\u4e00\u9635\u5b50\u611f\u89c9\u8fd8\u4e0d\u9519\uff0c\u7ecf\u8fc7\u4e00\u756a\u6574\u7406\u5b8c\u5584\u51b3\u5b9a\u5f00\u6e90\u3002\n\u4ed3\u5e93\u5730\u5740\uff1ahttps:\/\/github.com\/wi1dcard\/weekly-report\n\u5176\u5b9e\u6ca1\u4ec0\u4e48\u6280\u672f\u542b\u91cf\uff0c\u65e0\u975e\u5c31\u662f\u5229\u7528 Git \u7684\u63d0\u4ea4\u8bb0\u5f55\uff0c\u7f16\u6392\u6210 Markdown\u3002\nBTW\uff0c\u5176\u5b9e\u6216\u8bb8\u7528 Python \u5199\u4f1a\u66f4\u5408\u9002\u3002\n\u6700\u540e\uff0c\u6211\u7684\u5468\u62a5\u9879\u76ee VS Code \u914d\u7f6e\u5982\u4e0b\u3002\n{ &#34;[markdown]&#34;: { &#34;editor.wordWrap&#34;: &#34;off&#34;, &#34;editor.","title":"\u6211\u7684\u5468\u62a5\u5de5\u5177\u7bb1"},{"content":"\u8fc7\u7a0b \u4eca\u5929\u7528 ll \u547d\u4ee4\u5076\u7136\u89c2\u5bdf\u5230\u4e00\u4e2a\u7ec6\u8282\uff0c\u67d0\u4e9b\u6587\u4ef6\uff08\u5939\uff09\u5c5e\u6027\u540e\u9762\u5e26\u6709 @ \u5b57\u7b26\uff1a\n$ ll total 104 -rw-r--r--@ 1 user staff 0B 7 25 18:56 Icon? ... drwx------@ 15 user staff 480B 8 29 13:43 renren \u7ecf\u8fc7\u8c37\u6b4c\u4e00\u756a\uff0c\u539f\u6765\u8fd9\u4ee3\u8868\u6587\u4ef6\u542b\u6709 \u6269\u5c55\u5c5e\u6027\u3002\n\u4f7f\u7528 ll -@ \u53ef\u4ee5\u67e5\u770b\u8be6\u7ec6\u7684\u5c5e\u6027\u4fe1\u606f\u3002\ntotal 104 -rw-r--r--@ 1 jootu staff 0B 7 25 18:56 Icon? com.apple.FinderInfo 32B com.apple.ResourceFork 50K ... drwx------@ 15 user staff 480B 8 29 13:43 renren com.apple.quarantine 57B \u5bf9\u4e8e\u5f3a\u8feb\u75c7\u6765\u8bf4\uff0c\u5982\u4f55\u53bb\u9664\u6269\u5c55\u5c5e\u6027\u663e\u5f97\u5c24\u4e3a\u91cd\u8981\uff0c\u5c24\u5176\u662f\u4e0d\u80fd\u5bb9\u5fcd\u5728\u4e00\u6279\u540c\u4f5c\u7528\u7684\u6587\u4ef6\u91cc\u6709\u90a3\u4e48\u51e0\u4e2a\u300c\u7279\u6b8a\u7684\u5bb6\u4f19\u300d\ud83d\ude02\u3002\n\u5f53\u7136\uff0c\u5728\u53bb\u9664\u6269\u5c55\u5c5e\u6027\u4e4b\u524d\uff0c\u5148\u8981\u786e\u5b9a\u8fd9\u4e2a\u5c5e\u6027\u7684\u7528\u9014\u3002\u5982\u4e0a\uff0cIcon? \u662f\u7cfb\u7edf\u6587\u4ef6\uff0c\u6211\u6ca1\u6709\u4fee\u6539\uff1b\u800c renren \u662f\u4ece\u7f51\u4e0a\u4e0b\u8f7d\u89e3\u538b\u7684\u4e00\u4e2a\u6587\u4ef6\u5939\uff0c\u5e94\u8be5\u6ca1\u4ec0\u4e48\u732b\u817b\u624d\u5bf9\u3002\n\u518d\u6b21\u8c37\u6b4c\uff0c\u5f97\u77e5 com.apple.quarantine \u662f\u7cfb\u7edf\u81ea\u52a8\u6dfb\u52a0\u7684\uff1b\u50cf\u5728 macOS \u6253\u5f00\u4e0b\u8f7d\u7684\u6587\u4ef6\u65f6\uff0c\u7ecf\u5e38\u4f1a\u63d0\u793a\u300c\u8fd9\u662f\u4ece\u4e92\u8054\u7f51\u4e0b\u8f7d\u7684\u6587\u4ef6\u300d\u4e91\u4e91\uff0c\u4fbf\u662f\u8fd9\u4e2a\u5c5e\u6027\u7684\u4f5c\u7528\u3002\u5f53\u7528\u6237\u786e\u8ba4\u4e4b\u540e\uff0c\u8fd9\u4e2a\u5c5e\u6027\u4fbf\u4f1a\u88ab\u53d6\u6d88\u3002\n\u5f53\u7136\u6211\u4eec\u4e5f\u53ef\u4ee5\u624b\u52a8\u79fb\u9664\u5b83\uff0c\u4f7f\u7528 xattr \u547d\u4ee4\u5373\u53ef\u3002\nxattr -d com.apple.quarantine \u5b8c\u3002\n\u53c2\u8003  https:\/\/unix.stackexchange.com\/questions\/10\/what-does-the-mean-in-ls-l https:\/\/medium.com\/@jackyu\/%E7%A5%9E%E7%A7%98%E7%9A%84-mac-ea-com-apple-quarantine-553b4d265f36 https:\/\/www.jamf.com\/jamf-nation\/articles\/59\/managing-file-quarantine-attributes  ","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-ls-extended-attributes\/","summary":"\u8fc7\u7a0b \u4eca\u5929\u7528 ll \u547d\u4ee4\u5076\u7136\u89c2\u5bdf\u5230\u4e00\u4e2a\u7ec6\u8282\uff0c\u67d0\u4e9b\u6587\u4ef6\uff08\u5939\uff09\u5c5e\u6027\u540e\u9762\u5e26\u6709 @ \u5b57\u7b26\uff1a\n$ ll total 104 -rw-r--r--@ 1 user staff 0B 7 25 18:56 Icon? ... drwx------@ 15 user staff 480B 8 29 13:43 renren \u7ecf\u8fc7\u8c37\u6b4c\u4e00\u756a\uff0c\u539f\u6765\u8fd9\u4ee3\u8868\u6587\u4ef6\u542b\u6709 \u6269\u5c55\u5c5e\u6027\u3002","title":"macOS \u63a2\u5bfb\u6587\u4ef6\u6269\u5c55\u5c5e\u6027"},{"content":"\u5982\u9898\uff0c\u6709\u4e24\u79cd\u65b9\u6848\u5b9e\u73b0\u3002\n\u65b9\u6848\u4e00\uff1a\nYii::$app-&gt;controller-&gt;route; \u65b9\u6848\u4e8c\uff1a\nYii::$app-&gt;requestedRoute \u770b\u8fc7\u6e90\u7801\u540e\u624d\u77e5\u9053\u8fd9\u4fe9\u7684\u533a\u522b\u3002\n\u65b9\u6848\u4e00\u662f\u6839\u636e\u5f53\u524d\u8bf7\u6c42\u5df2\u521b\u5efa\u7684 module \/ controller \/ action\uff0c\u4e5f\u5c31\u662f\u5b9e\u9645\u5904\u7406\u5f53\u524d\u8bf7\u6c42\u7684\u6a21\u5757\u3001\u63a7\u5236\u5668\u3001\u65b9\u6cd5\u6240\u7ec4\u5408\u800c\u6210\u7684\u8def\u7531\uff0c\u7edd\u5bf9\u89c4\u8303\u3002\n\u65b9\u6848\u4e8c\u662f\u6839\u636e UrlManager::routeParam \u7b49\u914d\u7f6e\uff0c\u89e3\u6790\u8bf7\u6c42 URL \u53d6\u5f97\u7684\u8bbf\u95ee\u8def\u7531\uff0c\u4e0d\u4e00\u5b9a\u89c4\u8303\uff0c\u4f46\u5bf9\u7528\u6237\u53ef\u89c1\u3002\n\u901a\u5e38\u60c5\u51b5\u4e0b\u4e24\u79cd\u65b9\u6cd5\u5e94\u8be5\u662f\u7b49\u6548\u7684\uff1b\u67d0\u4e9b\u7279\u6b8a\u573a\u666f\uff0c\u4f8b\u5982\u4fee\u6539\u8fc7\u6839\u636e\u8def\u7531\u89e3\u6790\u521b\u5efa\u63a7\u5236\u5668\u7684\u8fc7\u7a0b\u3001\u5185\u90e8\u53cd\u4ee3\u91cd\u5199\u8fc7 URL \u7b49\uff0c\u5219\u6709\u53ef\u80fd\u5bfc\u81f4\u4e24\u65b9\u5f97\u5230\u7684\u503c\u4e0d\u4e00\u81f4\u3002\n\u6839\u636e\u4e0d\u540c\u4e1a\u52a1\u573a\u666f\u4f7f\u7528\u4e0d\u540c\u7684\u65b9\u6cd5\uff0c\u5bf9\u75c7\u4e0b\u836f\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/yii2-get-current-request-route\/","summary":"\u5982\u9898\uff0c\u6709\u4e24\u79cd\u65b9\u6848\u5b9e\u73b0\u3002\n\u65b9\u6848\u4e00\uff1a\nYii::$app-&gt;controller-&gt;route; \u65b9\u6848\u4e8c\uff1a\nYii::$app-&gt;requestedRoute \u770b\u8fc7\u6e90\u7801\u540e\u624d\u77e5\u9053\u8fd9\u4fe9\u7684\u533a\u522b\u3002\n\u65b9\u6848\u4e00\u662f\u6839\u636e\u5f53\u524d\u8bf7\u6c42\u5df2\u521b\u5efa\u7684 module \/ controller \/ action\uff0c\u4e5f\u5c31\u662f\u5b9e\u9645\u5904\u7406\u5f53\u524d\u8bf7\u6c42\u7684\u6a21\u5757\u3001\u63a7\u5236\u5668\u3001\u65b9\u6cd5\u6240\u7ec4\u5408\u800c\u6210\u7684\u8def\u7531\uff0c\u7edd\u5bf9\u89c4\u8303\u3002\n\u65b9\u6848\u4e8c\u662f\u6839\u636e UrlManager::routeParam \u7b49\u914d\u7f6e\uff0c\u89e3\u6790\u8bf7\u6c42 URL \u53d6\u5f97\u7684\u8bbf\u95ee\u8def\u7531\uff0c\u4e0d\u4e00\u5b9a\u89c4\u8303\uff0c\u4f46\u5bf9\u7528\u6237\u53ef\u89c1\u3002\n\u901a\u5e38\u60c5\u51b5\u4e0b\u4e24\u79cd\u65b9\u6cd5\u5e94\u8be5\u662f\u7b49\u6548\u7684\uff1b\u67d0\u4e9b\u7279\u6b8a\u573a\u666f\uff0c\u4f8b\u5982\u4fee\u6539\u8fc7\u6839\u636e\u8def\u7531\u89e3\u6790\u521b\u5efa\u63a7\u5236\u5668\u7684\u8fc7\u7a0b\u3001\u5185\u90e8\u53cd\u4ee3\u91cd\u5199\u8fc7 URL \u7b49\uff0c\u5219\u6709\u53ef\u80fd\u5bfc\u81f4\u4e24\u65b9\u5f97\u5230\u7684\u503c\u4e0d\u4e00\u81f4\u3002","title":"Yii2 \u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u8def\u7531\u4fe1\u606f"},{"content":"\u4e66\u63a5\u4e0a\u56de\uff0c\u524d\u9762\u8bf4\u5230\u5728\u8fc1\u79fb\u5185\u7ed9 Blueprint \u589e\u52a0\u81ea\u5b9a\u4e49\u7684 Macro\u3002\u90a3\u4e48\uff0c\u5f53\u6211\u4eec\u6bcf\u6b21\u4f7f\u7528 php artisan make:migration \u90fd\u9700\u8981\u624b\u52a8\u4fee\u6539\u4e00\u6b21\u6a21\u677f\u5417\uff1f\u8fd9\u4e0d\u6e05\u771f = =\u3002\n0x00 \u601d\u8def \u81ea\u5b9a\u4e49 make:migration \u6240\u4f7f\u7528\u7684 stub\uff08\u300c\u6869\u300d\uff0c\u53ef\u4ee5\u7406\u89e3\u4e3a\u6a21\u677f\uff09\u6587\u4ef6\u5373\u53ef\u3002\n\u5728\u5f00\u59cb\u4e4b\u524d\uff0c\u4f60\u9996\u5148\u9700\u8981\u521b\u5efa\u5c5e\u4e8e\u4f60\u7684 stubs \u6587\u4ef6\uff0c\u6211\u5efa\u8bae\u76f4\u63a5\u4ece Laravel 5.6 \u6e90\u7801 \u91cc\u62f7\u8d1d\u4e00\u4efd\u8fdb\u884c\u4fee\u6539\u5373\u53ef\u3002\n0x01 \u5b9e\u73b0   \u521b\u5efa\u4e00\u4e2a MigrationCreator \u7c7b\uff0c\u7ee7\u627f Illuminate\\Database\\Migrations\\MigrationCreator\uff1b\u5e76\u91cd\u5199 stubPath \u65b9\u6cd5\u3002\npublic function stubPath() { \/\/ \u66ff\u6362\u4e3a\u4f60\u7684 stubs \u8def\u5f84  return app_path(&#39;stubs&#39;); }   \u8001\u6837\u5b50\uff0c\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u63d0\u4f9b\u8005\u5e76\u5728 config\/app.php \u4e2d\u6ce8\u518c\uff0c\u8be6\u7ec6\u8fc7\u7a0b\u53c2\u89c1\u524d\u4e00\u7bc7\u535a\u6587\u3002\n  \u4f60\u9700\u8981\u624b\u52a8\u4fee\u6539\u6b64\u670d\u52a1\u63d0\u4f9b\u8005\uff0c\u7ee7\u627f Illuminate\\Database\\MigrationServiceProvider\u3002\n  \u91cd\u5199 registerCreator \u65b9\u6cd5\u3002\nprotected function registerCreator() { $this-&gt;app-&gt;singleton(&#39;migration.creator&#39;, function ($app) { \/\/ \u6ce8\u610f\u6b64\u5904\u7528\u5230\u7684 MigrationCreator \u662f\u6700\u521d\u81ea\u5b9a\u4e49\u7684  return new MigrationCreator($app[&#39;files&#39;]); }); }   \u5b8c\u6210\u3002\n  0x02 \u611f\u60f3 \u4ece Laravel \u5230 Yii \u518d\u56de\u5230 Laravel\uff0c\u611f\u89c9\u5c31\u50cf\u5403\u5230\u4e86\u5317\u65b9\u5bb6\u91cc\u7684\u997a\u5b50\uff0c\u771f\u9999\u8b66\u544a\uff08\u9003\uff09\u3002\n\u4e0d\u8fc7\u5176\u5b9e\u4e24\u65b9\u662f\u5404\u6709\u4f18\u52bf\u7684\u3002\n\u4e2a\u4eba\u611f\u89c9 Yii \u6765\u7684\u66f4\u52a0\u7b80\u7ea6\u76f4\u63a5\uff0c\u5c31\u50cf\u5b83\u7684 \u5b98\u65b9\u6587\u6863 \u6240\u8bf4\u7684\uff1a\n Yii \u7684\u4ee3\u7801\u7b80\u6d01\u4f18\u96c5\uff0c\u8fd9\u662f\u5b83\u7684\u7f16\u7a0b\u54f2\u5b66\u3002 \u5b83\u6c38\u8fdc\u4e0d\u4f1a\u4e3a\u4e86\u523b\u677f\u5730\u9075\u7167\u67d0\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u800c\u5bf9\u4ee3\u7801\u8fdb\u884c\u8fc7\u5ea6\u7684\u8bbe\u8ba1\u3002\n \u4e0d\u8fc7\u76f8\u6bd4\u4e4b\u4e0b\uff0c\u6211\u66f4\u559c\u6b22 Laravel \u7e41\u590d\u7cbe\u81f4\u7684\u4f18\u96c5\uff0c\u6b63\u5982 Laravel \u5b98\u7f51 \u7684 Slogan\uff1a\n The PHP Framework For Web Artisans\n \ud83d\ude02\u52aa\u529b\u505a\u4e2a\u827a\u672f\u5bb6\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-custom-migration-stub\/","summary":"\u4e66\u63a5\u4e0a\u56de\uff0c\u524d\u9762\u8bf4\u5230\u5728\u8fc1\u79fb\u5185\u7ed9 Blueprint \u589e\u52a0\u81ea\u5b9a\u4e49\u7684 Macro\u3002\u90a3\u4e48\uff0c\u5f53\u6211\u4eec\u6bcf\u6b21\u4f7f\u7528 php artisan make:migration \u90fd\u9700\u8981\u624b\u52a8\u4fee\u6539\u4e00\u6b21\u6a21\u677f\u5417\uff1f\u8fd9\u4e0d\u6e05\u771f = =\u3002\n0x00 \u601d\u8def \u81ea\u5b9a\u4e49 make:migration \u6240\u4f7f\u7528\u7684 stub\uff08\u300c\u6869\u300d\uff0c\u53ef\u4ee5\u7406\u89e3\u4e3a\u6a21\u677f\uff09\u6587\u4ef6\u5373\u53ef\u3002\n\u5728\u5f00\u59cb\u4e4b\u524d\uff0c\u4f60\u9996\u5148\u9700\u8981\u521b\u5efa\u5c5e\u4e8e\u4f60\u7684 stubs \u6587\u4ef6\uff0c\u6211\u5efa\u8bae\u76f4\u63a5\u4ece Laravel 5.","title":"Laravel 5.6 \u81ea\u5b9a\u4e49\u8fc1\u79fb\u6869\u4ee3\u7801"},{"content":"PHP \u57fa\u672c\u529f\u8db3\u591f\u624e\u5b9e\u7684\u60c5\u51b5\u4e0b\uff0c\u5f3a\u70c8\u5efa\u8bae\u5b66\u4e60 Laravel \u7684\u8fc7\u7a0b\u9664\u4e86\u9605\u8bfb\u5b98\u65b9\u6587\u6863\u5916\uff0c\u4ed4\u7ec6\u9605\u8bfb\u6846\u67b6\u6e90\u7801\uff1b\u6216\u8bb8\u4f1a\u6709\u5c0f\u60ca\u559c\u54df\u3002\n0x00 \u51c6\u5907  Laravel 5.6 php artisan make:migration ...  \u8fd1\u671f\u5728\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u9047\u5230\u8fd9\u4e48\u4e2a\u9700\u6c42\uff1a\u5728\u6240\u6709\u6a21\u578b\u8868\u5185\u90fd\u9700\u8981\u652f\u6301\u81ea\u589e\u4e3b\u952e id\u3001\u521b\u5efa\u65f6\u95f4\u3001\u66f4\u65b0\u65f6\u95f4\u4ee5\u53ca\u8f6f\u5220\u9664\uff0c\u4ee5\u5907\u4e0d\u65f6\u4e4b\u9700\u3002\n\u4e8e\u662f\u4e4e\u3002\u4f20\u7edf\u7684\u505a\u6cd5\u662f\uff0c\u5728\u6bcf\u4e2a\u8fc1\u79fb Schema::create \u56de\u8c03\u5185\uff0c\u90fd\u5199\u4e00\u904d $table-&gt;increments + softDeletes + timestamps\uff0c\u5c31\u50cf\u8fd9\u6837\uff1a\nSchema::create(&#39;foo&#39;, function (Blueprint $table) { $table-&gt;increments(&#39;id&#39;); $table-&gt;timestamps(); $table-&gt;softDeletes(); }); \u968f\u7740\u8868\u8d8a\u6765\u8d8a\u591a\uff0c\u91cd\u590d\u4ee3\u7801\u4e5f\u8d8a\u6765\u8d8a\u591a\uff0c\u5bf9\u4e8e\u6211\u8fd9\u4e2a\u5f3a\u8feb\u75c7\u6765\u8bf4\u7b80\u76f4\u770b\u7740\u76f8\u5f53\u4e0d\u723d\ud83d\ude02\uff1b\u800c\u4e14\u4e00\u65e6\u9700\u8981\u4fee\u6539\u5c31\u5f88\u5751\uff0cGit \u63d0\u4ea4\u8bb0\u5f55\u4e5f\u4f1a\u5f88\u6742\u4e71\u53c8\u4f4e\u4ef7\u503c\u3002\n0x01 \u601d\u8def \u6700\u5f00\u59cb\u60f3\u5230\u7684\u65b9\u6848\u662f\uff0c\u7ee7\u627f Schema Facade\uff0c\u91cd\u5199 create \u8c03\u7528\u7edf\u4e00\u7684\u56de\u8c03\u51fd\u6570\u52a0\u5165\u8fd9\u4e09\u4e2a\u5b57\u6bb5\uff1b\u4f46\u662f\u8fd9\u79cd\u65b9\u6cd5\u5177\u6709\u4fb5\u5165\u6027\uff0c\u4e5f\u5c31\u662f\u8bf4\u6240\u6709\u7684\u8868\u90fd\u5fc5\u987b\u5e26\u8fd9\u4e09\u4e2a\u5b57\u6bb5\uff0c\u540e\u671f\u4e2a\u522b\u8868\u5982\u679c\u6709\u7279\u6b8a\u9700\u6c42\u5c31\u6bd4\u8f83\u9ebb\u70e6\u4e86\u3002\n\u4e8e\u662f\u4e4e\u53bb\u770b\u4e86\u4e0b Blueprint \u7684\u6e90\u7801\uff0c\u53d1\u73b0\u4e00\u4e2a\u795e\u5668 Macroable trait\uff0c2333\u3002\n0x02 \u89e3\u51b3 \u9996\u5148\u5b9a\u4e49\u4e00\u4e2a\u670d\u52a1\u63d0\u4f9b\u8005\uff0c\u5e76\u4fee\u6539 config\/app.php \u7684 providers \u5185\u589e\u52a0\u6b64\u670d\u52a1\u63d0\u4f9b\u8005\u3002\nphp artisan make:provider BlueprintMacroProvider \/\/ config\/app.php &#39;providers&#39; =&gt; [ \/\/ ...  \/* * Application Service Providers... *\/ App\\Providers\\BlueprintMacroProvider::class, ] \u5728\u6b64\u63d0\u4f9b\u8005\u7684 register \u65b9\u6cd5\u5185\uff0c\u521b\u5efa Macro \u5373\u53ef\u3002\n\/\/ ... public function register() { Blueprint::macro(&#39;myColumns&#39;, function() { $table-&gt;increments(&#39;id&#39;); $table-&gt;timestamps(); $table-&gt;softDeletes(); }); } \u5728\u6240\u6709\u521b\u5efa\u8868\u7684\u56de\u8c03\u51fd\u6570\u5185\uff0c\u8c03\u7528\u6b64 Macro \u5373\u53ef\u3002\u4e8e\u662f\u4e0a\u9762\u7684\u4e09\u884c\u4ee3\u7801\u5c31\u53d8\u6210\u4e86\u4e00\u884c\uff1a\nSchema::create(&#39;foo&#39;, function (Blueprint $table) { $table-&gt;myColumns(); \/\/ \u65b9\u6cd5\u540d\u5c31\u662f\u6211\u4eec\u5b9a\u4e49 macro \u65f6\u4f7f\u7528\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002 }); \u641e\u5b9a\uff0c\u7edf\u4e00\u5230 myColumns \u91cc\u5904\u7406\u3002\n0x03 \u62d3\u5c55 \u6709\u5174\u8da3\u53ef\u4ee5\u770b\u4e0b https:\/\/laravel.com\/docs\/5.6\/responses#response-macros\uff0c\u8fd9\u91cc\u6709 Laravel HTTP Response \u5bf9\u4e8e\u5176 Macro \u7684\u4ecb\u7ecd\u3002\u5b9e\u9645\u4e0a\uff0cLaravel \u7684\u54cd\u5e94\u4e5f\u662f\u540c\u6837\u4f7f\u7528 Macroable trait \u5b9e\u73b0\u7684\u6b64\u529f\u80fd\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-blueprint-macro\/","summary":"PHP \u57fa\u672c\u529f\u8db3\u591f\u624e\u5b9e\u7684\u60c5\u51b5\u4e0b\uff0c\u5f3a\u70c8\u5efa\u8bae\u5b66\u4e60 Laravel \u7684\u8fc7\u7a0b\u9664\u4e86\u9605\u8bfb\u5b98\u65b9\u6587\u6863\u5916\uff0c\u4ed4\u7ec6\u9605\u8bfb\u6846\u67b6\u6e90\u7801\uff1b\u6216\u8bb8\u4f1a\u6709\u5c0f\u60ca\u559c\u54df\u3002\n0x00 \u51c6\u5907  Laravel 5.6 php artisan make:migration ...  \u8fd1\u671f\u5728\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u9047\u5230\u8fd9\u4e48\u4e2a\u9700\u6c42\uff1a\u5728\u6240\u6709\u6a21\u578b\u8868\u5185\u90fd\u9700\u8981\u652f\u6301\u81ea\u589e\u4e3b\u952e id\u3001\u521b\u5efa\u65f6\u95f4\u3001\u66f4\u65b0\u65f6\u95f4\u4ee5\u53ca\u8f6f\u5220\u9664\uff0c\u4ee5\u5907\u4e0d\u65f6\u4e4b\u9700\u3002\n\u4e8e\u662f\u4e4e\u3002\u4f20\u7edf\u7684\u505a\u6cd5\u662f\uff0c\u5728\u6bcf\u4e2a\u8fc1\u79fb Schema::create \u56de\u8c03\u5185\uff0c\u90fd\u5199\u4e00\u904d $table-&gt;increments + softDeletes + timestamps\uff0c\u5c31\u50cf\u8fd9\u6837\uff1a","title":"Laravel 5.6 \u7ed9 Blueprint \u589e\u52a0\u81ea\u5b9a\u4e49\u65b9\u6cd5"},{"content":"\u5e8f \u6700\u8fd1\u65b0\u9879\u76ee\u5199 README\uff0c\u5728\u7f16\u6392\u5b9e\u4f53\u547d\u540d\u534f\u5b9a\u4e2d\u82f1\u5bf9\u7167\u7684\u65f6\u5019\uff0c\u6709\u4f7f\u7528\u5230 Markdown \u7684\u8868\u683c\u3002\u90a3\u4e48\u5982\u4f55\u6309\u7167\u67d0\u5217\u7684\u5b57\u6bcd\u987a\u5e8f\u6392\u5e8f Markdown \u8868\u683c\u5462\uff1f\u5b9e\u9645\u4e0a\uff0c\u4e00\u6761 Shell \u547d\u4ee4\u5c31\u8db3\u4ee5\u89e3\u51b3\u3002\u8bf7\u770b\u5927\u4f6c\u7684\u5b9e\u73b0\u3002\n\u6b63\u6587 TableFlip \u76ee\u524d\u8fd8\u65e0\u6cd5\u6839\u636e\u5217\u6392\u5e8f\u8868\u683c. \u6240\u4ee5\u6211\u4eec\u4e0d\u5f97\u4e0d\u4f7f\u7528\u5176\u4ed6\u65b9\u6cd5\uff0c\u6bd4\u5982 Shell \u6216\u8005 Terminal \u547d\u4ee4.\n\u9996\u5148\uff0c\u6211\u4eec\u5047\u8bbe\u4f60\u7684 Markdown \u8868\u683c\u7531\u4e00\u4e2a\u4e24\u884c\u7684\u8868\u5934\u5f00\u59cb\uff0c\u5e76\u4e14\u6bcf\u884c\u5f00\u5934\u90fd\u6709\u7ba1\u9053\u64cd\u4f5c\u7b26\uff08|\uff09\uff0c\u5c31\u50cf\u8fd9\u6837\uff1a\n| a | b | c | d | | - | - | - | - | | 1 | 2 | 3 | 4 | | 9 | 1 | 2 | 3 | | 3 | 4 | 5 | 6 | \u63a5\u4e0b\u6765\uff0c\u4f60\u4fbf\u53ef\u4ee5\u4f7f\u7528\u5982\u4e0b\u547d\u4ee4\uff0c\u6309\u7167\u7b2c\u4e09\u5217\uff08c \u5217\uff09\u5bf9\u8868\u683c\u8fdb\u884c\u6392\u5e8f\uff1a\ntail -n +3 table.md | sort --field-separator=\\| --key=4 \u89e3\u91ca:\n tail \u547d\u4ee4\u8bfb\u53d6\u6587\u4ef6\u7684\u5c3e\u90e8\uff1btail -n +3 \u4ece\u5c3e\u90e8\u5f00\u59cb\u8bfb\u53d6\u4e00\u4e2a\u6587\u4ef6\uff0c\u76f4\u5230\u7b2c\u4e09\u884c\u7ed3\u675f\uff1b\u6392\u9664\u4e86\u524d\u4e24\u884c\uff0c\u4e5f\u5c31\u662f\u8868\u5934\u3002 sort \u547d\u4ee4\u6392\u5e8f\u6587\u672c\u8f93\u5165\uff1b--field-separator=\\| \u6307\u5b9a\u6392\u5e8f\u547d\u4ee4\u4f7f\u7528\u7ba1\u9053\u5206\u9694\u7b26\uff08|\uff09\u800c\u975e tab \u4f5c\u4e3a\u5217\u5206\u9694\u7b26\uff1b--key=4 \u8bbe\u7f6e\u6839\u636e\u7b2c 4 \u5217\u8fdb\u884c\u6392\u5e8f\uff08\u6ce8\u610f\uff0c\u6b64\u5904\u5b9e\u9645\u4e0a\u662f\u7b2c 3 \u5217\uff1b\u56e0\u4e3a\u5982\u679c\u8868\u683c\u884c\u7531\u5217\u5206\u9694\u7b26\u4e5f\u5c31\u662f\u7ba1\u9053\u64cd\u4f5c\u7b26\u5f00\u5934\uff0c\u90a3\u5b83\u4e5f\u4f1a\u88ab\u7b97\u8fdb\u6392\u5e8f\u5217\u91cc\uff09\u3002  \u8f93\u51fa\u4e3a:\n| 9 | 1 | 2 | 3 | | 1 | 2 | 3 | 4 | | 3 | 4 | 5 | 6 | \u4f60\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528 head \u5408\u5e76 tail \u628a\u8868\u5934\u91cd\u65b0\u6dfb\u52a0\u56de\u53bb\uff0chead \u547d\u4ee4\u5c06\u4f1a\u8f93\u51fa\u6587\u4ef6\u7684\u5f00\u5934\u4e24\u884c\u3002\nhead -n 2 table.md &amp;&amp; tail -n +3 table.md | sort --field-separator=\\| --key=4 \u5c31\u662f\u8fd9\u6837\uff1a\n| a | b | c | d | | - | - | - | - | | 9 | 1 | 2 | 3 | | 1 | 2 | 3 | 4 | | 3 | 4 | 5 | 6 | \u6700\u540e\uff0c\u53ea\u9700\u8981\u4f7f\u7528 &gt; sorted_file.md \u628a\u8f93\u51fa\u91cd\u5b9a\u5411\u5230\u4e00\u4e2a\u65b0\u6587\u4ef6\u5373\u53ef\u4fdd\u5b58\uff1a\n(head -n 2 table.md &amp;&amp; tail -n +3 table.md | sort --field-separator=\\| --key=4) &gt; sorted_table.md \u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/christiantietze.de\/posts\/2017\/05\/sort-markdown-tables-shell\/\n\u788e\u788e\u5ff5 \u5370\u8c61\u4e2d\uff0c\u4e03\u6708\u7ed3\u675f\u4e5f\u6709\u8fc7\u611f\u53f9\u3002\u65f6\u95f4\u98de\u5feb\uff0c\u9a6c\u4e0a\u5230\u4e86\u516b\u6708\u5e95\uff0c\u4e00\u8f6c\u773c\u5c31\u5230\u4e86\u4e5d\u6708\u5f00\u5b66\uff08\u548c\u5973\u670b\u53cb\u89c1\u9762\uff09\u7684\u65e5\u5b50\u3002\nemmmm\uff0c\u8fd9\u4e2a\u6708\u505a\u4e2a\u7b80\u5355\u603b\u7ed3\u3002\n\u4e0a\u534a\u4e2a\u6708\u5728\u5fd9\u7740\u4f7f\u7528\u4e03\u6708\u5e95\u5c01\u88c5\u7684 \u652f\u4ed8\u5b9d SDK \u628a\u516c\u53f8\u9879\u76ee\u96c6\u6210\u5230\u652f\u4ed8\u5b9d\u3002\n\u4e0b\u534a\u4e2a\u6708\u4e3a\u5373\u5c06\u5f00\u59cb\u7684\u65b0\u9879\u76ee\u505a\u51c6\u5907\u5de5\u4f5c\uff0c\u6240\u4ee5\u624d\u6709\u4e86\u8fd1\u671f\u4e00\u4e9b\u5173\u4e8e Laravel \u7684\u535a\u6587\uff1b\u65b0\u9879\u76ee\u65e2\u7136\u8001\u677f\u4fe1\u4efb\u5730\u4e22\u7ed9\u6211\u505a\u540e\u7aef\u67b6\u6784\uff0c\u90a3\u5c31\u6beb\u4e0d\u72b9\u8c6b\u5730\u91c7\u7528\u793e\u533a\u6d3b\u8dc3\u3001\u4ee3\u7801\u4f18\u96c5\u3001\u8f6e\u5b50\u591a\u7684\u5f53\u7ea2\u70b8\u5b50\u9e21 Laravel \u5566\u3002\n\u53e6\u5916\u8003\u8651\u5230 Laravel \u5728\u4f18\u96c5\u8def\u4e0a\u8d8a\u8d70\u8d8a\u8fdc\uff0c\u7531\u4e8e\u5e76\u53d1\u6027\u80fd\u4e5f\u4e0d\u5bb9\u5ffd\u89c6\uff0c\u6240\u4ee5\u6700\u8fd1\u53ef\u80fd\u8981\u5f00\u5173\u4e8e Swoole \u7684\u5751\u4e86\u3002\n\u4e4b\u524d\u4e00\u76f4\u81ea\u5df1\u73a9 Swoole \uff0c\u5199\u4e00\u4e9b\u957f\u94fe\u63a5\u7684\u5c0f\u9879\u76ee\u548c\u5c0f\u73a9\u5177\uff0c\u8fd9\u662f\u7b2c\u4e00\u6b21\u5c1d\u8bd5\u628a Swoole \u5927\u89c4\u6a21\u7528\u5728\u5546\u4e1a\u9879\u76ee\u91cc\uff0c\u60f3\u60f3\u8fd8\u662f\u6709\u70b9\u5c0f\u6fc0\u52a8 \/\u659c\u773c\u7b11\u3002\n2333\uff0c\u671f\u5f85\u63a5\u4e0b\u6765\u7684\u6311\u6218\uff0c\u7ed9\u81ea\u5df1\u52a0\u6cb9\uff01\n\u4e5d\u6708\uff0c\u4f60\u597d\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/sort-markdown-tables-shell\/","summary":"\u5e8f \u6700\u8fd1\u65b0\u9879\u76ee\u5199 README\uff0c\u5728\u7f16\u6392\u5b9e\u4f53\u547d\u540d\u534f\u5b9a\u4e2d\u82f1\u5bf9\u7167\u7684\u65f6\u5019\uff0c\u6709\u4f7f\u7528\u5230 Markdown \u7684\u8868\u683c\u3002\u90a3\u4e48\u5982\u4f55\u6309\u7167\u67d0\u5217\u7684\u5b57\u6bcd\u987a\u5e8f\u6392\u5e8f Markdown \u8868\u683c\u5462\uff1f\u5b9e\u9645\u4e0a\uff0c\u4e00\u6761 Shell \u547d\u4ee4\u5c31\u8db3\u4ee5\u89e3\u51b3\u3002\u8bf7\u770b\u5927\u4f6c\u7684\u5b9e\u73b0\u3002\n\u6b63\u6587 TableFlip \u76ee\u524d\u8fd8\u65e0\u6cd5\u6839\u636e\u5217\u6392\u5e8f\u8868\u683c. \u6240\u4ee5\u6211\u4eec\u4e0d\u5f97\u4e0d\u4f7f\u7528\u5176\u4ed6\u65b9\u6cd5\uff0c\u6bd4\u5982 Shell \u6216\u8005 Terminal \u547d\u4ee4.\n\u9996\u5148\uff0c\u6211\u4eec\u5047\u8bbe\u4f60\u7684 Markdown \u8868\u683c\u7531\u4e00\u4e2a\u4e24\u884c\u7684\u8868\u5934\u5f00\u59cb\uff0c\u5e76\u4e14\u6bcf\u884c\u5f00\u5934\u90fd\u6709\u7ba1\u9053\u64cd\u4f5c\u7b26\uff08|\uff09\uff0c\u5c31\u50cf\u8fd9\u6837\uff1a","title":"\u5728\u7ec8\u7aef\u5185\u6392\u5e8f Markdown \u8868\u683c"},{"content":"Serialize &amp; unserialize data to &amp; from JSON. Compatible with serialized data and supported accessing unserialized data as a object &amp; array.\nclass Serializer { public function __construct() { } public function encode($value) { return json_encode($value, JSON_UNESCAPED_UNICODE); } public function decode($value) { $res = json_decode($value, true); if ($res === null) { if (json_last_error() == JSON_ERROR_NONE) { return $res; } if (json_last_error() != JSON_ERROR_SYNTAX) { $error = json_last_error_msg(); throw new \\InvalidArgumentException(&#34;{$error}: `{$value}` cannot be decoded!&#34;); } $res = unserialize($value); if ($res === false) { $value = preg_replace_callback( &#39;\/s:([0-9]+):\\&#34;(.*?)\\&#34;;\/&#39;, function ($matches) { return &#34;s:&#34; . strlen($matches[2]) . &#39;:&#34;&#39; . $matches[2] . &#39;&#34;;&#39;; }, $value ); $res = unserialize($value); if ($res === false) { throw new \\InvalidArgumentException(&#34;`{$value}` cannot be unserialized!&#34;); } } } if (!is_object($res) &amp;&amp; !is_array($res)) { return $res; } return new \\ArrayObject($res, \\ArrayObject::ARRAY_AS_PROPS); } } Reference:\n https:\/\/stackoverflow.com\/questions\/3148712\/regex-code-to-fix-corrupt-serialized-php-data http:\/\/php.net\/manual\/en\/function.json-decode.php http:\/\/php.net\/manual\/en\/function.unserialize.php  ","permalink":"https:\/\/wi1dcard.dev\/posts\/php-json-serializer\/","summary":"Serialize &amp; unserialize data to &amp; from JSON. Compatible with serialized data and supported accessing unserialized data as a object &amp; array.","title":"PHP JSON Serializer"},{"content":"Laravel \u63d0\u4f9b where \u65b9\u6cd5\u548c Route::pattern \u65b9\u6cd5\uff0c\u7528\u4e8e\u8bbe\u7f6e\u67d0\u4e2a\u8def\u7531\u53c2\u6570\u5fc5\u987b\u5339\u914d\u6307\u5b9a\u8868\u8fbe\u5f0f\uff0c\u5219\u6b64\u8def\u7531\u624d\u4f1a\u88ab\u5339\u914d\u3002\n\u90a3\u4e48\uff0c\u5982\u4f55\u8bbe\u7f6e\u6392\u9664\u67d0\u4e2a\u300c\u5173\u952e\u8bcd\u300d\uff08\u6216\u8005\u6211\u4eec\u79f0\u5b83\u4e3a\u300c\u7279\u6b8a\u53c2\u6570\u503c\u300d\uff09\uff0c\u53ea\u6709\u8fd9\u4e2a\u5173\u952e\u8bcd\u4e0d\u5339\u914d\uff0c\u5176\u5b83\u90fd\u5339\u914d\u5462\uff1f\n\u4e3e\u4e2a\u4f8b\u5b50 Route::domain(&#39;{user}.example.com&#39;); Route::pattern(&#39;user&#39;, &#39;???&#39;); ??? \u5904\u4ee3\u8868\u4e8c\u7ea7\u57df\uff0c\u901a\u5e38\u4e0d\u53ef\u4ee5\u8bbe\u7f6e\u4e3a\u4e00\u4e9b\u654f\u611f\u4fdd\u7559\u8bcd\uff0c\u6bd4\u5982 www \/ admin \u7b49\u3002\n\u89e3\u51b3\u65b9\u6848 \u5b9e\u9645\u4e0a\uff0cLaravel \u7684\u8def\u7531\u53c2\u6570\u5339\u914d\uff0c\u4f7f\u7528\u7684\u6b63\u662f\u6b63\u5219\u8868\u8fbe\u5f0f\u3002\u6240\u4ee5\uff0c\u8fd9\u5c31\u597d\u529e\u4e86\u3002\n\u6839\u636e\u4e1a\u52a1\u903b\u8f91\uff0c\u8fd9\u91cc\u5206\u4e24\u79cd\u60c5\u51b5\u3002\n  \u5168\u5b57\u5339\u914d\u3002\n\u4f8b\u5982\uff0c\u521a\u521a\u90a3\u79cd\u60c5\u51b5\u3002www \u80af\u5b9a\u4e0d\u53ef\u4ee5\uff0c\u4f46\u5305\u542b www \u7684\u5b57\u7b26\u4e32\u662f\u53ef\u4ee5\u7684\u3002\n\u6b63\u5219\uff1a.*(?&lt;!^www)\n\u5982\u679c\u9700\u8981\u5339\u914d\u591a\u4e2a\uff0c\u53ef\u4ee5\uff1a.*(?&lt;!^www|admin)\u3002\n  \u6a21\u7cca\u5339\u914d\u3002\n\u4f8b\u5982\uff0c\u4e0d\u80fd\u5305\u542b fuck \/ porn \u7b49\uff0c\u5b57\u7b26\u4e32\u4f55\u5904\u90fd\u4e0d\u5141\u8bb8\u5305\u542b\u6b64\u7c7b\u5173\u952e\u8bcd\u3002\n\u6b63\u5219\uff1a((?!fuck).)*\n\u540c\u7406\uff0c\u5339\u914d\u591a\u4e2a\uff1a((?!fuck|porn).)*\u3002\n  \u611f\u8a00 \u8fd1\u671f\u53c8\u5f00\u59cb\u6478 Laravel\uff0c\u8fd8\u662f\u4e00\u5982\u65e2\u5f80\u7684\u6027\u611f\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-route-pattern-exclude\/","summary":"Laravel \u63d0\u4f9b where \u65b9\u6cd5\u548c Route::pattern \u65b9\u6cd5\uff0c\u7528\u4e8e\u8bbe\u7f6e\u67d0\u4e2a\u8def\u7531\u53c2\u6570\u5fc5\u987b\u5339\u914d\u6307\u5b9a\u8868\u8fbe\u5f0f\uff0c\u5219\u6b64\u8def\u7531\u624d\u4f1a\u88ab\u5339\u914d\u3002\n\u90a3\u4e48\uff0c\u5982\u4f55\u8bbe\u7f6e\u6392\u9664\u67d0\u4e2a\u300c\u5173\u952e\u8bcd\u300d\uff08\u6216\u8005\u6211\u4eec\u79f0\u5b83\u4e3a\u300c\u7279\u6b8a\u53c2\u6570\u503c\u300d\uff09\uff0c\u53ea\u6709\u8fd9\u4e2a\u5173\u952e\u8bcd\u4e0d\u5339\u914d\uff0c\u5176\u5b83\u90fd\u5339\u914d\u5462\uff1f\n\u4e3e\u4e2a\u4f8b\u5b50 Route::domain(&#39;{user}.example.com&#39;); Route::pattern(&#39;user&#39;, &#39;???&#39;); ??? \u5904\u4ee3\u8868\u4e8c\u7ea7\u57df\uff0c\u901a\u5e38\u4e0d\u53ef\u4ee5\u8bbe\u7f6e\u4e3a\u4e00\u4e9b\u654f\u611f\u4fdd\u7559\u8bcd\uff0c\u6bd4\u5982 www \/ admin \u7b49\u3002\n\u89e3\u51b3\u65b9\u6848 \u5b9e\u9645\u4e0a\uff0cLaravel \u7684\u8def\u7531\u53c2\u6570\u5339\u914d\uff0c\u4f7f\u7528\u7684\u6b63\u662f\u6b63\u5219\u8868\u8fbe\u5f0f\u3002\u6240\u4ee5\uff0c\u8fd9\u5c31\u597d\u529e\u4e86\u3002","title":"Laravel 5.6 \u8def\u7531\u53c2\u6570\u6392\u9664\u5339\u914d"},{"content":"\u7f51\u4e0a\u7684\u6587\u7ae0\u666e\u904d\u662f Laravel 5.5 \u7248\u672c\uff0c\u800c\u65e5\u5fd7\u7cfb\u7edf\u5728 5.6 \u7248\u672c\u5347\u7ea7\u65f6\u8fdb\u884c\u4e86\u90e8\u5206\u6539\u52a8\uff0c\u539f\u6709\u65b9\u6cd5\u57fa\u672c\u90fd\u5931\u6548\u4e86\u3002\u672c\u6587\u6839\u636e Laravel 5.6 \u6587\u6863\u7684\u6307\u5f15\uff0c\u5b9e\u73b0\u4f7f\u7528 MongoDB \u5b58\u50a8\u6846\u67b6\u65e5\u5fd7\u3002\n0x00 \u51c6\u5907 MongoDB Engine \u9996\u5148\uff0c\u5b89\u88c5 MongoDB\uff0c\u53c2\u89c1 \u5b98\u65b9\u6587\u6863\u3002\nMongoDB Driver\uff08PHP Extension\uff09 \u5176\u6b21\uff0c\u5b89\u88c5 PHP mongodb \u6269\u5c55\uff0c\u53c2\u89c1 \u5b98\u65b9\u6587\u6863\u3002\nGitHub\uff1ahttps:\/\/github.com\/mongodb\/mongo-php-driver\u3002\nMongoDB Library\uff08Wrapper Package\uff09 \u6700\u540e\uff0c\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u4f60\u8fd8\u9700\u8981\u4e00\u4e2a\u9ad8\u5ea6\u5c01\u88c5\u7684\u5305\u88c5\u5e93\uff1b\u4f7f\u7528 MongoDB \u5b98\u65b9\u63d0\u4f9b\u5373\u53ef\uff0c\u53c2\u89c1 \u5b98\u65b9\u6587\u6863\u3002\nGitHub\uff1ahttps:\/\/github.com\/mongodb\/mongo-php-library\u3002\n0x01 \u914d\u7f6e \u6253\u5f00 config\/logging.php\uff0c\u4fee\u6539\u5176 channels\u3002\nreturn [ \/\/ ...  &#39;channels&#39; =&gt; [ \/\/ ...  &#39;mongodb&#39; =&gt; [ \/\/ \u6b64\u5904\u53ef\u4ee5\u6839\u636e\u9700\u6c42\u8c03\u6574  &#39;driver&#39; =&gt; &#39;custom&#39;, \/\/ \u6b64\u5904\u5fc5\u987b\u4e3a `custom`  &#39;via&#39; =&gt; CreateCustomLogger::class, \/\/ \u5f53 `driver` \u8bbe\u7f6e\u4e3a custom \u65f6\uff0c\u4f7f\u7528 `via` \u914d\u7f6e\u9879\u6240\u6307\u5411\u7684\u5de5\u5382\u7c7b\u521b\u5efa logger  \/\/ \u4ee5\u4e0b env \u914d\u7f6e\u540d\u53ef\u4ee5\u6839\u636e\u9700\u6c42\u8c03\u6574  &#39;server&#39; =&gt; env(&#39;LOG_MONGO_SERVER&#39;, &#39;mongodb:\/\/localhost:27017&#39;), &#39;database&#39; =&gt; env(&#39;LOG_MONGO_DB&#39;, &#39;logs&#39;), &#39;collection&#39; =&gt; env(&#39;LOG_MONGO_COLLECTION&#39;, &#39;logs&#39;), &#39;level&#39; =&gt; env(&#39;LOG_MONGO_LEVEL&#39;, &#39;debug&#39;), \/\/ \u65e5\u5fd7\u7ea7\u522b  ], ], ]; \u63a5\u7740\u4f60\u9700\u8981\u5c06 default \u4fee\u6539\u4e3a mongodb\uff0c\u4e5f\u53ef\u4ee5\u4fee\u6539 .env\u3002\nreturn [ &#39;default&#39; =&gt; env(&#39;LOG_CHANNEL&#39;, &#39;mongodb&#39;), \/\/ \u6211\u76f4\u63a5\u5c06\u9ed8\u8ba4\u503c\u4fee\u6539\u4e3a mongodb\uff0c\u4e5f\u5c31\u662f channels \u5185\u65b0\u589e\u7684\u914d\u7f6e\u9879\u3002  \/\/ ... ] 0x02 \u5b9e\u73b0 \u627e\u4e2a\u5408\u9002\u7684\u4f4d\u7f6e\uff08\u6211\u4f7f\u7528 app\/Logging\uff09\u521b\u5efa CreateCustomLogger.php\u3002\nuse Monolog\\Logger; use Monolog\\Handler\\MongoDBHandler; use Monolog\\Processor\\WebProcessor; class CreateCustomLogger { \/** * Create a custom Monolog instance. * * @param array $config * @return \\Monolog\\Logger *\/ public function __invoke(array $config) { $logger = new Logger(&#39;&#39;); \/\/ \u521b\u5efa Logger  $handler = new MongoDBHandler( \/\/ \u521b\u5efa Handler  new \\MongoDB\\Client($config[&#39;server&#39;]), \/\/ \u521b\u5efa MongoDB \u5ba2\u6237\u7aef\uff08\u4f9d\u8d56 mongodb\/mongodb\uff09  $config[&#39;database&#39;], $config[&#39;collection&#39;] ); $handler-&gt;setLevel($config[&#39;level&#39;]); $logger-&gt;pushHandler($handler); \/\/ \u6302\u8f7d Handler  $logger-&gt;pushProcessor(new WebProcessor($_SERVER)); \/\/ \u8bb0\u5f55\u989d\u5916\u7684\u8bf7\u6c42\u4fe1\u606f  return $logger; } } 0x03 \u5b8c\u6210 \u597d\u4e86\uff0c\u63a5\u4e0b\u6765\u53ef\u4ee5\u6267\u884c php artisan tinker\uff0c\u8f93\u5165 Log::warning(...) \u6d4b\u8bd5\u4f60\u7684\u6210\u679c\u4e86\u3002\n\u522b\u5fd8\u8bb0\u628a MongoDB \u670d\u52a1\u542f\u52a8\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-logging-with-mongodb\/","summary":"\u7f51\u4e0a\u7684\u6587\u7ae0\u666e\u904d\u662f Laravel 5.5 \u7248\u672c\uff0c\u800c\u65e5\u5fd7\u7cfb\u7edf\u5728 5.6 \u7248\u672c\u5347\u7ea7\u65f6\u8fdb\u884c\u4e86\u90e8\u5206\u6539\u52a8\uff0c\u539f\u6709\u65b9\u6cd5\u57fa\u672c\u90fd\u5931\u6548\u4e86\u3002\u672c\u6587\u6839\u636e Laravel 5.6 \u6587\u6863\u7684\u6307\u5f15\uff0c\u5b9e\u73b0\u4f7f\u7528 MongoDB \u5b58\u50a8\u6846\u67b6\u65e5\u5fd7\u3002\n0x00 \u51c6\u5907 MongoDB Engine \u9996\u5148\uff0c\u5b89\u88c5 MongoDB\uff0c\u53c2\u89c1 \u5b98\u65b9\u6587\u6863\u3002\nMongoDB Driver\uff08PHP Extension\uff09 \u5176\u6b21\uff0c\u5b89\u88c5 PHP mongodb \u6269\u5c55\uff0c\u53c2\u89c1 \u5b98\u65b9\u6587\u6863\u3002","title":"Laravel 5.6 \u4f7f\u7528 MongoDB \u5b58\u50a8\u6846\u67b6\u65e5\u5fd7"},{"content":"\u5f53\u6211\u4eec\u7684 Git \u4ed3\u5e93\u8d8a\u6765\u8d8a\u5927\uff0c\u6216\u8005\u4e0d\u5c0f\u5fc3\u63d0\u4ea4\u4e86\u4e8c\u8fdb\u5236\u5927\u6587\u4ef6\uff0c\u5982\u4f55\u5feb\u901f\u627e\u51fa\u4ed3\u5e93\u5185\u7684\u300c\u7f6a\u9b41\u7978\u9996\u300d\uff1f\n\u5b9e\u8df5 \u5b9e\u9645\u4e0a\u975e\u5e38\u7b80\u5355\uff0c\u4e00\u6761\u547d\u4ee4\u5c31\u80fd\u641e\u5b9a\u3002\ngit rev-list --objects --all \\ # | git cat-file --batch-check=&#39;%(objecttype) %(objectname) %(objectsize) %(rest)&#39; \\ | sed -n &#39;s\/^blob \/\/p&#39; \\ | sort -r -n -k 2 \\ | head -10 \\ | cut -c 1-12,41- \\ | numfmt --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest  \u6ce8\u610f\uff0c\u5728 macOS \u4f7f\u7528\u6b64\u547d\u4ee4\u9700\u8981\u5b89\u88c5 brew install coreutils --with-default-names\u3002\n\u82e5\u4f60\u5df2\u7ecf\u5b89\u88c5\u4f46\u5e76\u6ca1\u6709\u4f7f\u7528 --with-default-names \u9009\u9879\uff0c\u5219\u9700\u8981\u66ff\u6362 numfmt \u4e3a gnumfmt\u3002\n \u6216\u8bb8\u6709\u4eba\u8bf4\uff0c\u4f7f\u7528 du \u547d\u4ee4\u4e5f\u53ef\u4ee5\u5b9e\u73b0\u3002\u4f46\u8fd9\u6837\u4f1a\u7f3a\u5c11 gitignore \u7684\u652f\u6301\uff0c\u5e76\u4e14\u65e0\u6cd5\u67e5\u627e\u5230\u5df2\u5220\u9664\u4f46\u5b58\u5728\u4e8e\u63d0\u4ea4\u5386\u53f2\u7684\u6587\u4ef6\u3002\n\u5907\u9009 \u53e6\u5916\uff0c\u5728\u7801\u4e91\u8fd8\u770b\u5230\u4e00\u79cd\u65b9\u6cd5\uff1b\u4f46\u76f8\u6bd4\u524d\u9762\u7684\u65b9\u6cd5\u7565\u900a\uff0c\u4e0d\u80fd\u663e\u793a\u6587\u4ef6\u5927\u5c0f\uff0c\u4e5f\u6ca1\u6709\u5b8c\u5168\u91c7\u7528\u7ba1\u9053\u5904\u7406\uff0c\u662f\u5426\u8db3\u591f\u4e25\u8c28\u6709\u5f85\u8003\u8bc1\u3002\u4f5c\u4e3a\u5907\u9009\u547d\u4ee4\u5427\u3002\ngit rev-list --objects --all | grep -E &#34;`git verify-pack -v .git\/objects\/pack\/*.idx | sort -r -n -k 3 | head -10 | awk &#39;{print$1}&#39; | sed &#39;:a;N;$!ba;s\/\\n\/|\/g&#39;`&#34; \u53c2\u8003  https:\/\/stackoverflow.com\/questions\/10622179\/how-to-find-identify-large-commits-in-git-history http:\/\/git.mydoc.io\/?t=83153  ","permalink":"https:\/\/wi1dcard.dev\/posts\/git-find-large-file\/","summary":"\u5f53\u6211\u4eec\u7684 Git \u4ed3\u5e93\u8d8a\u6765\u8d8a\u5927\uff0c\u6216\u8005\u4e0d\u5c0f\u5fc3\u63d0\u4ea4\u4e86\u4e8c\u8fdb\u5236\u5927\u6587\u4ef6\uff0c\u5982\u4f55\u5feb\u901f\u627e\u51fa\u4ed3\u5e93\u5185\u7684\u300c\u7f6a\u9b41\u7978\u9996\u300d\uff1f\n\u5b9e\u8df5 \u5b9e\u9645\u4e0a\u975e\u5e38\u7b80\u5355\uff0c\u4e00\u6761\u547d\u4ee4\u5c31\u80fd\u641e\u5b9a\u3002\ngit rev-list --objects --all \\ # | git cat-file --batch-check=&#39;%(objecttype) %(objectname) %(objectsize) %(rest)&#39; \\ | sed -n &#39;s\/^blob \/\/p&#39; \\ | sort -r -n -k 2 \\ | head -10 \\ | cut -c 1-12,41- \\ | numfmt --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest  \u6ce8\u610f\uff0c\u5728 macOS \u4f7f\u7528\u6b64\u547d\u4ee4\u9700\u8981\u5b89\u88c5 brew install coreutils --with-default-names\u3002","title":"Git \u4ed3\u5e93\u67e5\u627e\u5df2\u8ffd\u8e2a\u7684\u5927\u6587\u4ef6"},{"content":"\u4e66\u63a5\u4e0a\u56de\u3002\u4e0a\u6587\u7ed3\u5c3e\uff0c\u8bb2\u89e3\u4e86\u5f15\u7528\u7684\u5999\u7528\u3002\u521a\u597d\uff0c\u5728\u6211\u73b0\u5728\u6240\u5904\u516c\u53f8\u7684\u4e1a\u52a1\u91cc\u6709\u4e00\u5904\u7528\u9012\u5f52\u5b9e\u73b0\u7684\u300c\u7701\u5e02\u533a\u300d\u5206\u7ea7\u5217\u8868\uff1b\u672c\u6587\u5c06\u8fd9\u4e00\u7528\u9014\u642c\u8fdb\u751f\u4ea7\u73af\u5883\uff0c\u901a\u8fc7\u4f18\u5316\u6b64\u7701\u5e02\u533a\u5217\u8868\uff0c\u8bd5\u8bd5\u771f\u6b63\u7684\u6548\u679c\u5982\u4f55\u3002\n\u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u4e0a\u4ee3\u7801\u3002\n\u7701\u5e02\u533a\u5217\u8868\u7ed3\u6784 array( 1 =&gt; array( &#39;id&#39; =&gt; 1, &#39;name&#39; =&gt; &#39;\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd&#39;, &#39;parent_id&#39; =&gt; 0, &#39;level&#39; =&gt; &#39;country&#39;, ), 2 =&gt; array( &#39;id&#39; =&gt; 2, &#39;name&#39; =&gt; &#39;\u5317\u4eac\u5e02&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 20 =&gt; array( &#39;id&#39; =&gt; 20, &#39;name&#39; =&gt; &#39;\u5929\u6d25\u5e02&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 38 =&gt; array( &#39;id&#39; =&gt; 38, &#39;name&#39; =&gt; &#39;\u6cb3\u5317\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 218 =&gt; array( &#39;id&#39; =&gt; 218, &#39;name&#39; =&gt; &#39;\u5c71\u897f\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 349 =&gt; array( &#39;id&#39; =&gt; 349, &#39;name&#39; =&gt; &#39;\u5185\u8499\u53e4\u81ea\u6cbb\u533a&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 465 =&gt; array( &#39;id&#39; =&gt; 465, &#39;name&#39; =&gt; &#39;\u8fbd\u5b81\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), ... ); \u4f18\u5316\u524d \/** * \u83b7\u53d6\u4ee5\u7236\u7ea7 ID \u4e3a $parent_id \u4e3a\u6839\u8282\u70b9\u7684\u6811\u578b\u7ed3\u6784\u6570\u7ec4 * * @param array $arr * @param int $level \u6811\u578b\u5f53\u524d\u5c42 * @param int $parent_id \u7236\u7ea7id * @param int $floor \u6811\u578b\u603b\u5c42\u6570 * @return array *\/ public static function getList(&amp;$arr, $level = 0, $parent_id = 1, $floor = 3) { if ($level != 0) { $empty = $arr[$parent_id]; $empty[&#39;list&#39;] = []; $emptyPointer = &amp;$empty[&#39;list&#39;]; } else { $empty = []; $emptyPointer = &amp;$empty; } if ($level &lt; $floor) { $ok = false; foreach ($arr as $index =&gt; &amp;$item) { if ($item[&#39;parent_id&#39;] == $parent_id) { $data = self::getList($arr, $level + 1, $index); array_push($emptyPointer, $data); $ok = true; } if ($ok &amp;&amp; $item[&#39;parent_id&#39;] != $parent_id) { break; } } } return $empty; } \u4f18\u5316\u540e function getStructuredTree($list) { $tree = []; foreach ($list as &amp;$item) { $parent_id = $item[&#39;parent_id&#39;]; if (isset($list[$parent_id]) &amp;&amp; !empty($list[$parent_id])) { $list[$parent_id][&#39;list&#39;][] = &amp;$item; } else { $tree[] = &amp;$item; } } \/\/ unset($item);  return $tree[0][&#39;list&#39;]; \/\/ \u6839\u8282\u70b9\u53ea\u6709\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd\uff0c\u6240\u4ee5\u76f4\u63a5\u8fd4\u56de\u4e2d\u56fd\u7684\u6240\u6709\u5b50\u8282\u70b9 } \u6548\u679c \u4ee5\u4e0b\u4e3a\u6b64\u51fd\u6570\u6267\u884c 1000 \u6b21\u53d6\u5e73\u5747\u503c\u3002\n    \u51fd\u6570\u8fd0\u884c\u65f6\u95f4 (ms) memory_get_peak_usage() \u5cf0\u503c\u5185\u5b58 (MB)     \u4f18\u5316\u524d 157.65 2516192 2.39   \u4f18\u5316\u540e 2.01 987872 0.94    \u4ec5\u4f9b\u53c2\u8003\uff0c\u4e0d\u540c\u73af\u5883\u751f\u6210\u7684\u5177\u4f53\u6570\u503c\u53ef\u80fd\u5dee\u5f02\u8f83\u5927\uff0c\u53ea\u5173\u6ce8\u4f18\u5316\u524d\u540e\u7684\u5bf9\u6bd4\u5c31\u597d\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-fastest-create-tree-from-list\/","summary":"\u4e66\u63a5\u4e0a\u56de\u3002\u4e0a\u6587\u7ed3\u5c3e\uff0c\u8bb2\u89e3\u4e86\u5f15\u7528\u7684\u5999\u7528\u3002\u521a\u597d\uff0c\u5728\u6211\u73b0\u5728\u6240\u5904\u516c\u53f8\u7684\u4e1a\u52a1\u91cc\u6709\u4e00\u5904\u7528\u9012\u5f52\u5b9e\u73b0\u7684\u300c\u7701\u5e02\u533a\u300d\u5206\u7ea7\u5217\u8868\uff1b\u672c\u6587\u5c06\u8fd9\u4e00\u7528\u9014\u642c\u8fdb\u751f\u4ea7\u73af\u5883\uff0c\u901a\u8fc7\u4f18\u5316\u6b64\u7701\u5e02\u533a\u5217\u8868\uff0c\u8bd5\u8bd5\u771f\u6b63\u7684\u6548\u679c\u5982\u4f55\u3002\n\u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u4e0a\u4ee3\u7801\u3002\n\u7701\u5e02\u533a\u5217\u8868\u7ed3\u6784 array( 1 =&gt; array( &#39;id&#39; =&gt; 1, &#39;name&#39; =&gt; &#39;\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd&#39;, &#39;parent_id&#39; =&gt; 0, &#39;level&#39; =&gt; &#39;country&#39;, ), 2 =&gt; array( &#39;id&#39; =&gt; 2, &#39;name&#39; =&gt; &#39;\u5317\u4eac\u5e02&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 20 =&gt; array( &#39;id&#39; =&gt; 20, &#39;name&#39; =&gt; &#39;\u5929\u6d25\u5e02&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 38 =&gt; array( &#39;id&#39; =&gt; 38, &#39;name&#39; =&gt; &#39;\u6cb3\u5317\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 218 =&gt; array( &#39;id&#39; =&gt; 218, &#39;name&#39; =&gt; &#39;\u5c71\u897f\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 349 =&gt; array( &#39;id&#39; =&gt; 349, &#39;name&#39; =&gt; &#39;\u5185\u8499\u53e4\u81ea\u6cbb\u533a&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), 465 =&gt; array( &#39;id&#39; =&gt; 465, &#39;name&#39; =&gt; &#39;\u8fbd\u5b81\u7701&#39;, &#39;parent_id&#39; =&gt; 1, &#39;level&#39; =&gt; &#39;province&#39;, ), .","title":"PHP \u5feb\u901f\u626b\u63cf\u5217\u8868\u521b\u5efa\u65e0\u9650\u6781\u5206\u7c7b\u6811"},{"content":"\u6700\u8fd1\u5728\u5173\u6ce8\u300cPHP \u5f15\u7528\u300d\u8fd9\u4e00\u8bdd\u9898\uff0c\u770b\u8fc7\u4e0d\u5c11\u6df1\u5ea6\u6587\u7ae0\uff0c\u5bf9 PHP \u91cc\u7684\u300c\u5f15\u7528\u300d\u6709\u4e86\u66f4\u6df1\u7684\u7406\u89e3\u3002\n0x00 \u9996\u5148\u770b\u5982\u4e0b\u4ee3\u7801\uff1a\n$foo[&#39;hello&#39;] = &#39;0&#39;; $bar = &amp;$foo[&#39;hello&#39;]; \/\/ \u5f15\u7528\uff01 $tipi = $foo; $tipi[&#39;hello&#39;] = &#39;1&#39;; print_r($foo); \u95ee\uff1a\u8f93\u51fa 0 \u8fd8\u662f\u8f93\u51fa 1\uff1f\u7b54\u6848\u662f 1\u3002\n\u539f\u7406\u4f55\u5728\uff1f\nPHP \u5185\u6838\u4f7f\u7528 zval \u7ed3\u6784\u5b58\u50a8\u53d8\u91cf\uff0c\u5728 PHP \u4ee3\u7801\u91cc\uff0c\u6211\u4eec\u5229\u7528 xdebug_debug_zval \u51fd\u6570\u4e00\u63a2\u7a76\u7adf\u3002\n\u4fee\u6539\u5982\u4e0a\u4ee3\u7801\uff1a\n$foo[&#39;hello&#39;] = &#39;0&#39;; xdebug_debug_zval(&#39;foo&#39;); $bar = &amp;$foo[&#39;hello&#39;]; \/\/ \u5f15\u7528\uff01 xdebug_debug_zval(&#39;foo&#39;); $tipi = $foo; $tipi[&#39;hello&#39;] = &#39;1&#39;; print_r($foo); \u8f93\u51fa\u5982\u4e0b\uff1a\nfoo: (refcount=1, is_ref=0)=array ('hello' =&gt; (refcount=1, is_ref=0)='0') foo: (refcount=1, is_ref=0)=array ('hello' =&gt; (refcount=2, is_ref=1)='0') $foo['hello'] \u4ece\u975e\u5f15\u7528\u53d8\u91cf\uff08is_ref=0\uff09\u53d8\u4e3a\u5f15\u7528\u53d8\u91cf\uff08is_ref=1\uff09\uff0c\u800c\u5f15\u7528\u8ba1\u6570\u5219\u4e3a refcount=2\u3002\n\u4e3a\u4ec0\u4e48\u4f1a\u8fd9\u6837\uff1f\n\u6839\u636e PHP: \u5f15\u7528\u505a\u4ec0\u4e48 - Manual \u7684\u89e3\u91ca\uff1a\n $a =&amp; $b; \u8fd9\u610f\u5473\u7740 $a \u548c $b \u6307\u5411\u4e86\u540c\u4e00\u4e2a\u53d8\u91cf\u3002\n$a \u548c $b \u5728\u8fd9\u91cc\u662f\u5b8c\u5168\u76f8\u540c\u7684\uff0c\u8fd9\u5e76\u4e0d\u662f $a \u6307\u5411\u4e86 $b \u6216\u8005\u76f8\u53cd\uff0c\u800c\u662f $a \u548c $b \u6307\u5411\u4e86\u540c\u4e00\u4e2a\u5730\u65b9\u3002\n \u7ed3\u5408\u6211\u4eec\u7684\u4f8b\u5b50\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u5f53 $bar = &amp;$foo['hello']; \u6267\u884c\u65f6\uff0c$bar \u548c $foo['hello'] \u90fd\u6210\u4e3a\u4e86\u300c\u5f15\u7528\u53d8\u91cf\u300d\uff0c\u4e14\u5b83\u4eec\u300c\u6307\u5411\u4e86\u540c\u4e00\u4e2a\u5730\u65b9\u300d\u3002\n\u90a3\u4e48\u5f53\u6211\u4eec\u590d\u5236\u6b64\u6570\u7ec4\u65f6\uff0c\u4e5f\u590d\u5236\u4e86\u5b83 hello \u5143\u7d20\u7684\u5f15\u7528\uff1b\u5f53 $tipi['hello'] = '1'; \u6267\u884c\u65f6\uff0c\u5c31\u4fee\u6539\u4e86 tipi['hello'] \u3001$foo['hello'] \u4ee5\u53ca $bar \u6240\u6307\u5411\u7684\u300c\u540c\u4e00\u4e2a\u5730\u65b9\u300d\u3002\n\u4e8e\u662f\uff0c$foo['hello'] \u7684\u503c\u7406\u6240\u5f53\u7136\u5730\u6210\u4e3a\u4e86 1\u3002\n0x01 \u7565\u6709\u6df1\u5165\u5f15\u7528\u7684 PHPer \u5e94\u8be5\u90fd\u8bd5\u8fc7\u8fd9\u79cd\u8bed\u6cd5\uff1a\nfor ($list as &amp;$value) { $value = &#39;foo&#39;; } PHP \u5728\u63a7\u5236\u7ed3\u6784\u540e\u4e0d\u4f1a\u56de\u6536\u53d8\u91cf\uff0c\u6b64\u5904\u4e0d\u591a\u8bb2\u89e3\uff1b\u4e8e\u662f\u521a\u521a\u7684\u5751\uff0c\u5176\u5b9e\u53ef\u4ee5\u5ef6\u4f38\u4e00\u4e0b\u3002\n$foo[&#39;hello&#39;] = &#39;0&#39;; $foo[&#39;world&#39;] = &#39;A&#39;; foreach($foo as &amp;$value) { \/\/ \u5f15\u7528\uff01  \/\/ Do nothing. } $tipi = $foo; $tipi[&#39;hello&#39;] = &#39;1&#39;; $tipi[&#39;world&#39;] = &#39;B&#39;; print_r($foo); \u6b64\u5904\u8f93\u51fa\u5982\u4e0b\uff1a\nArray ( [hello] =&gt; 0 [world] =&gt; B ) hello \u6b63\u5e38\uff0c\u800c world \u88ab\u4fee\u6539\u4e3a B\uff01\u539f\u56e0\u53ef\u4ee5\u7ed3\u5408 xdebug_debug_zval \u51fd\u6570\u81ea\u884c\u63a2\u7a76\u3002\n\u6240\u4ee5\uff0c\u968f\u624b unset($value); \u662f\u4e2a\u597d\u4e60\u60ef\u3002\n0x02 \u5176\u5b9e\u5f15\u7528\u4e5f\u4e0d\u5168\u662f\u5751\u3002\u597d\u5904\u8fd8\u662f\u5927\u5927\u5730\u6709\u3002\n\u4e3e\u4f8b\uff1a\n$catList = [ &#39;1&#39; =&gt; [&#39;id&#39; =&gt; 1, &#39;name&#39; =&gt; &#39;\u989c\u8272&#39;, &#39;parent_id&#39; =&gt; 0], &#39;2&#39; =&gt; [&#39;id&#39; =&gt; 2, &#39;name&#39; =&gt; &#39;\u89c4\u683c&#39;, &#39;parent_id&#39; =&gt; 0], &#39;3&#39; =&gt; [&#39;id&#39; =&gt; 3, &#39;name&#39; =&gt; &#39;\u767d\u8272&#39;, &#39;parent_id&#39; =&gt; 1], &#39;4&#39; =&gt; [&#39;id&#39; =&gt; 4, &#39;name&#39; =&gt; &#39;\u9ed1\u8272&#39;, &#39;parent_id&#39; =&gt; 1], &#39;5&#39; =&gt; [&#39;id&#39; =&gt; 5, &#39;name&#39; =&gt; &#39;\u5927&#39;, &#39;parent_id&#39; =&gt; 2], &#39;6&#39; =&gt; [&#39;id&#39; =&gt; 6, &#39;name&#39; =&gt; &#39;\u5c0f&#39;, &#39;parent_id&#39; =&gt; 2], &#39;7&#39; =&gt; [&#39;id&#39; =&gt; 7, &#39;name&#39; =&gt; &#39;\u9ec4\u8272&#39;, &#39;parent_id&#39; =&gt; 1], ]; \u5982\u4f55\u5b9e\u73b0\u5c06\u5982\u4e0a\u987a\u5e8f\u8868\u8f6c\u6362\u4e3a\u5c42\u7ea7\u6811\uff1f\n\u8fc7\u53bb\uff0c\u6216\u8005\u8bf4\u901a\u5e38\u60c5\u51b5\u4e0b\u6211\u4eec\u9996\u5148\u60f3\u5230\u7684\u662f\u9012\u5f52\u56de\u6eaf\u3002\n\u4e0d\u8fc7\uff0c\u5229\u7528 PHP \u7684\u5f15\u7528\u7279\u6027\uff0c\u53ef\u4ee5\u5c06\u65f6\u95f4\u590d\u6742\u5ea6\u964d\u4f4e\u5230 O(n)\u3002\n$treeData = []; foreach ($catList as $item) { if (isset($catList[$item[&#39;parent_id&#39;]]) &amp;&amp; !empty($catList[$item[&#39;parent_id&#39;]])) { \/\/ \u5b50\u5206\u7c7b  $catList[$item[&#39;parent_id&#39;]][&#39;children&#39;][] = &amp;$catList[$item[&#39;id&#39;]]; } else { \/\/ \u4e00\u7ea7\u5206\u7c7b  $treeData[] = &amp;$catList[$item[&#39;id&#39;]]; } } var_export($treeData); \u5177\u4f53\u4f18\u5316\u6548\u679c\uff0c\u8bf7\u53c2\u8003\u4e0b\u4e00\u7bc7\u535a\u6587\u3002\n0xFF \u53c2\u8003  PHP: \u5f15\u7528\u7684\u89e3\u91ca - Manual PHP: \u5f15\u7528\u8ba1\u6570\u57fa\u672c\u77e5\u8bc6 - Manual \u7b2c\u516d\u7ae0 \u00bb \u7b2c\u516d\u8282 \u5199\u65f6\u590d\u5236\uff08Copy On Write\uff09 | TIPI: \u6df1\u5165\u7406\u89e3 PHP \u5185\u6838 PHP \u7684\u5f15\u7528\uff0c\u4f60\u77e5\u9053\u591a\u5c11 - \u6398\u91d1 \u6df1\u5165\u7406\u89e3 PHP \u539f\u7406\u4e4b\u53d8\u91cf\u5206\u79bb\/\u5f15\u7528(Variables Separation) | \u98ce\u96ea\u4e4b\u9685  ","permalink":"https:\/\/wi1dcard.dev\/posts\/php-reference-variable\/","summary":"\u6700\u8fd1\u5728\u5173\u6ce8\u300cPHP \u5f15\u7528\u300d\u8fd9\u4e00\u8bdd\u9898\uff0c\u770b\u8fc7\u4e0d\u5c11\u6df1\u5ea6\u6587\u7ae0\uff0c\u5bf9 PHP \u91cc\u7684\u300c\u5f15\u7528\u300d\u6709\u4e86\u66f4\u6df1\u7684\u7406\u89e3\u3002\n0x00 \u9996\u5148\u770b\u5982\u4e0b\u4ee3\u7801\uff1a\n$foo[&#39;hello&#39;] = &#39;0&#39;; $bar = &amp;$foo[&#39;hello&#39;]; \/\/ \u5f15\u7528\uff01 $tipi = $foo; $tipi[&#39;hello&#39;] = &#39;1&#39;; print_r($foo); \u95ee\uff1a\u8f93\u51fa 0 \u8fd8\u662f\u8f93\u51fa 1\uff1f\u7b54\u6848\u662f 1\u3002","title":"PHP \u5f15\u7528\u8be6\u89e3 - \u8e29\u5751\u4e0e\u5999\u7528"},{"content":"\u524d\u4e9b\u5929\u626b\u63cf\u5927\u6587\u4ef6\u7684\u65f6\u5019\uff0c\u53d1\u73b0\u4e00\u4e2a\u76ee\u5f55 ~\/Library\/Application Support\/Code\/User\/workspaceStorage \u5360\u7528\u975e\u5e38\u5927\uff0c\u770b\u8d77\u6765\u7f6a\u9b41\u7978\u9996\u50cf\u662f VSCode\uff1b\n\u4e8e\u662f\u8c37\u6b4c\u4e00\u756a\uff0c\u53d1\u73b0 GitHub \u4e0a\u6709\u4e00\u6761 Issue \u8ba8\u8bba\u8fd9\u4e8b\u3002\n\u4f20\u9001\u95e8\uff1ahttps:\/\/github.com\/Microsoft\/vscode\/issues\/39692\n\u5176\u4e2d\u6709\u4e00\u6761 Comment \u662f\u8fd9\u6837\u7684\uff1a\n All extension should be able to recreate their storage although they might answer some questions. @llv22 is there a folder that is especially big? Would be good to know if there is an extension leaving garbage behind.\n \u5927\u81f4\u610f\u601d\u662f\uff0c\u6240\u6709\u7684\u6269\u5c55\u90fd\u5e94\u8be5\u80fd\u91cd\u5efa\u8fd9\u4e2a\u6587\u4ef6\u5939\uff0c\u53ef\u80fd\u662f\u67d0\u4e2a\u6269\u5c55\u7559\u4e86\u4e00\u5806\u5783\u573e\u6587\u4ef6\u5728\u91cc\u9762\u3002\n\u5e76\u4e14\u8fd9\u4e2a\u6587\u4ef6\u5939\u5b58\u50a8\u7684\u903b\u8f91\u662f\u6309\u7167\u8def\u5f84\u533a\u5206\u7684&hellip;\n\u6240\u4ee5\u8fd9\u5c31\u5bfc\u81f4\uff1a\u5982\u679c\u4f60\u6709\u4e2a\u5f88\u5927\u7684\u9879\u76ee\uff0cVSCode \u5f00\u4e86\u4e00\u5806\u6269\u5c55\uff0c\u5199\u4e86\u4e00\u6bb5\u65f6\u95f4\u7136\u540e\u628a\u9879\u76ee\u6587\u4ef6\u5939\u79fb\u52a8\u5230\u5176\u5b83\u8def\u5f84\uff0c\u5c31\u6709\u53ef\u80fd\u5bfc\u81f4\u539f\u6765\u7684\u5783\u573e\u7559\u5728\u90a3\uff0c\u73b0\u6709\u7684\u53c8\u7ee7\u7eed\u5f00\u59cb\u5806\u3002\n\u770b\u4e86\u4e0b\u6211\u81ea\u5df1\u7684\u60c5\u51b5\uff0c\u662f\u7531\u4e8e PHP Intelephense \u5efa\u7acb\u5927\u91cf\u7d22\u5f15\uff0c\u5e76\u4e14\u52a8\u8fc7\u9879\u76ee\u6587\u4ef6\u5939\u5bfc\u81f4\u7684\u3002\n\u65e2\u7136\u77e5\u9053\u53ef\u4ee5\u5220\uff0c\u90a3\u5c31\u597d\u529e\u4e86\u3002\u6253\u5f00\u6b64\u6587\u4ef6\u5939\uff0c\u770b\u4e00\u4e0b\u4fee\u6539\u65f6\u95f4\uff0c\u592a\u8001\u7684\u76f4\u63a5\u5220\u6389\uff0c\u5b8c\u4e8b\u513f\u3002\n\u53e6\u5916\u987a\u624b\u52a0\u5230 Time Machine \u6392\u9664\u5217\u8868\uff0c\u52a0\u5feb\u5907\u4efd\u901f\u5ea6\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/vscode-clear-workspace-storage\/","summary":"\u524d\u4e9b\u5929\u626b\u63cf\u5927\u6587\u4ef6\u7684\u65f6\u5019\uff0c\u53d1\u73b0\u4e00\u4e2a\u76ee\u5f55 ~\/Library\/Application Support\/Code\/User\/workspaceStorage \u5360\u7528\u975e\u5e38\u5927\uff0c\u770b\u8d77\u6765\u7f6a\u9b41\u7978\u9996\u50cf\u662f VSCode\uff1b\n\u4e8e\u662f\u8c37\u6b4c\u4e00\u756a\uff0c\u53d1\u73b0 GitHub \u4e0a\u6709\u4e00\u6761 Issue \u8ba8\u8bba\u8fd9\u4e8b\u3002\n\u4f20\u9001\u95e8\uff1ahttps:\/\/github.com\/Microsoft\/vscode\/issues\/39692\n\u5176\u4e2d\u6709\u4e00\u6761 Comment \u662f\u8fd9\u6837\u7684\uff1a\n All extension should be able to recreate their storage although they might answer some questions.","title":"VS Code \u6e05\u7406\u5de5\u4f5c\u533a\u6587\u4ef6"},{"content":"2333&hellip; \u6700\u8fd1\u53d1\u73b0\u4e00\u4e2a\u795e\u5947\u7684\u7ad9\u70b9\uff0c\u968f\u673a\u751f\u6210 Git commit message\u3002\nhttp:\/\/whatthecommit.com\/\n\u81f3\u4e8e\u7528\u5230 Git \u4e0a\uff1a\ngit commit -m $(curl -s http:\/\/whatthecommit.com\/index.txt) \ud83d\ude02\n \u4e03\u6708\u9a6c\u4e0a\u53c8\u8981\u8fc7\u53bb\u4e86\u3002\n\u6700\u8fd1\u5728\u5c01\u88c5\u652f\u4ed8\u5b9d\u7684 SDK\uff0c\u6240\u4ee5\u535a\u5ba2\u6709\u4e00\u5c0f\u9635\u5b50\u6ca1\u6709\u66f4\u65b0\u3002\n\u53e6\u5916\u6709\u4e2a\u611f\u60f3\uff0c\u4e0b\u6b21\u8df3\u69fd\u7684\u8bdd\uff0c\u5e0c\u671b\u80fd\u9009\u4e2a\u6709 GitHub\uff0c\u5927\u5bb6\u90fd\u70ed\u7231\u5e76\u6295\u8eab\u4e8e\u5f00\u6e90\u4e8b\u4e1a\u7684\u516c\u53f8\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/git-randomize-commit-message\/","summary":"2333&hellip; \u6700\u8fd1\u53d1\u73b0\u4e00\u4e2a\u795e\u5947\u7684\u7ad9\u70b9\uff0c\u968f\u673a\u751f\u6210 Git commit message\u3002\nhttp:\/\/whatthecommit.com\/\n\u81f3\u4e8e\u7528\u5230 Git \u4e0a\uff1a\ngit commit -m $(curl -s http:\/\/whatthecommit.com\/index.txt) \ud83d\ude02\n \u4e03\u6708\u9a6c\u4e0a\u53c8\u8981\u8fc7\u53bb\u4e86\u3002\n\u6700\u8fd1\u5728\u5c01\u88c5\u652f\u4ed8\u5b9d\u7684 SDK\uff0c\u6240\u4ee5\u535a\u5ba2\u6709\u4e00\u5c0f\u9635\u5b50\u6ca1\u6709\u66f4\u65b0\u3002","title":"\u7279\u55b5\u7684\u968f\u673a Git \u63d0\u4ea4\u4fe1\u606f"},{"content":"\u65b9\u6cd5\u5f88\u591a\uff0c\u5217\u51fa\u51e0\u4e2a\uff0c\u4ee5\u4f9b\u53c2\u8003\u3002\n  Laravel \u6e90\u7801\u91cc\u6252\u51fa\u6765\u7684 class_basename \u8f85\u52a9\u51fd\u6570\nbasename(str_replace(&#39;\\\\&#39;, &#39;\/&#39;, $class));   substr \u5b9e\u73b0\nsubstr(strrchr($class, &#34;\\\\&#34;), 1); \/\/ or substr($class, strrpos($class, &#39;\\\\&#39;) + 1);   explode \u5b9e\u73b0\narray_pop(explode(&#39;\\\\&#39;, $class));   ReflectionClass \u5b9e\u73b0\n(new \\ReflectionClass($class))-&gt;getShortName();   \u5176\u4e2d\uff0cReflectionClass \u662f\u6700\u5feb\u6700\u4fdd\u9669\u7684\u65b9\u6848\uff0c\u4f46\u6b64\u7c7b\u5fc5\u987b\u5b9e\u9645\u5b58\u5728\uff0c\u4e0d\u5b58\u5728\u5219\u4f1a\u629b\u51fa ReflectionException: Class \\Foo\\Bar does not exist\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-class-name-without-namespace\/","summary":"\u65b9\u6cd5\u5f88\u591a\uff0c\u5217\u51fa\u51e0\u4e2a\uff0c\u4ee5\u4f9b\u53c2\u8003\u3002\n  Laravel \u6e90\u7801\u91cc\u6252\u51fa\u6765\u7684 class_basename \u8f85\u52a9\u51fd\u6570\nbasename(str_replace(&#39;\\\\&#39;, &#39;\/&#39;, $class));   substr \u5b9e\u73b0\nsubstr(strrchr($class, &#34;\\\\&#34;), 1); \/\/ or substr($class, strrpos($class, &#39;\\\\&#39;) + 1);   explode \u5b9e\u73b0","title":"PHP \u83b7\u53d6\u4e0d\u5e26\u547d\u540d\u7a7a\u95f4\u7684\u7c7b\u540d"},{"content":" \u4e0d\u7528\u6269\u5c55\u5b9e\u73b0\u7684 PHP \u52a0\u5bc6\u6df7\u6dc6\uff0c\u6ca1\u6709\u9760\u8c31\u7684\u4ea7\u54c1\uff0c\u8fd8\u6709\u53ef\u80fd\u5bfc\u81f4\u903b\u8f91\u51fa\u95ee\u9898\uff0c\u800c\u4e14\u65e0\u6cd5\u68c0\u67e5\u3002 \u7531\u4e8e\u73af\u5883\u56e0\u7d20\u7684\u5dee\u5f02\u5728 PHP \u5185\u4ea7\u751f\u7684\u5f71\u54cd\u662f\u975e\u5e38\u5de8\u5927\u7684\uff0c\u505a SaaS \uff08\u670d\u52a1\u5668\u7531\u5ba2\u6237\u8fd0\u7ef4\uff09\u8fd8\u662f\u4e0d\u7528 PHP \u4e3a\u597d\u3002 \u300c\u7b80\u5355\u6613\u5b66\u300d\u3001\u300c\u5411\u524d\u517c\u5bb9\u6027\u597d\u300d\u7684\u7279\u8d28\u4f7f\u5f97 PHP \u7684\u4ee3\u7801\u53ef\u80fd\u6781\u81f4\u4f18\u96c5\uff0c\u4e5f\u6709\u53ef\u80fd\u4e00\u6ee9\u70c2\u6ce5\uff1b\u300c\u53ef\u4ee5\u8fd0\u884c\u300d\u7684\u4ee3\u7801\u6216\u8bb8\u5b58\u5728\u5de8\u5927\u7684\u53ef\u8bfb\u6027\u5dee\u8ddd\u3001\u6027\u80fd\u5dee\u8ddd\u3002 MySQL BINLOG \u4e5f\u4e0d\u662f\u90a3\u4e48\u597d\u73a9\u7684&hellip; \u82e5\u662f\u6570\u636e\u5e93\u7ed3\u6784\u6709\u6539\u52a8\uff0c\u60f3\u8981\u5b9e\u73b0\u95ea\u56de\u6050\u6015\u4e0d\u662f\u90a3\u4e48\u7b80\u5355\u3002 \u51c6\u5907\u5f00\u5751 Golang\u3002  \u96be\u53d7\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/mysql-bloody-lessons\/","summary":"\u4e0d\u7528\u6269\u5c55\u5b9e\u73b0\u7684 PHP \u52a0\u5bc6\u6df7\u6dc6\uff0c\u6ca1\u6709\u9760\u8c31\u7684\u4ea7\u54c1\uff0c\u8fd8\u6709\u53ef\u80fd\u5bfc\u81f4\u903b\u8f91\u51fa\u95ee\u9898\uff0c\u800c\u4e14\u65e0\u6cd5\u68c0\u67e5\u3002 \u7531\u4e8e\u73af\u5883\u56e0\u7d20\u7684\u5dee\u5f02\u5728 PHP \u5185\u4ea7\u751f\u7684\u5f71\u54cd\u662f\u975e\u5e38\u5de8\u5927\u7684\uff0c\u505a SaaS \uff08\u670d\u52a1\u5668\u7531\u5ba2\u6237\u8fd0\u7ef4\uff09\u8fd8\u662f\u4e0d\u7528 PHP \u4e3a\u597d\u3002 \u300c\u7b80\u5355\u6613\u5b66\u300d\u3001\u300c\u5411\u524d\u517c\u5bb9\u6027\u597d\u300d\u7684\u7279\u8d28\u4f7f\u5f97 PHP \u7684\u4ee3\u7801\u53ef\u80fd\u6781\u81f4\u4f18\u96c5\uff0c\u4e5f\u6709\u53ef\u80fd\u4e00\u6ee9\u70c2\u6ce5\uff1b\u300c\u53ef\u4ee5\u8fd0\u884c\u300d\u7684\u4ee3\u7801\u6216\u8bb8\u5b58\u5728\u5de8\u5927\u7684\u53ef\u8bfb\u6027\u5dee\u8ddd\u3001\u6027\u80fd\u5dee\u8ddd\u3002 MySQL BINLOG \u4e5f\u4e0d\u662f\u90a3\u4e48\u597d\u73a9\u7684&hellip; \u82e5\u662f\u6570\u636e\u5e93\u7ed3\u6784\u6709\u6539\u52a8\uff0c\u60f3\u8981\u5b9e\u73b0\u95ea\u56de\u6050\u6015\u4e0d\u662f\u90a3\u4e48\u7b80\u5355\u3002 \u51c6\u5907\u5f00\u5751 Golang\u3002  \u96be\u53d7\u3002","title":"\u6570\u636e\u5e93\u8840\u7684\u6559\u8bad"},{"content":"\u6700\u8fd1\u4e3a\u4e86\u5c3d\u53ef\u80fd\u4f18\u96c5\u5730\u5b9e\u73b0\u4ea7\u54c1\u9700\u6c42\uff0c\u5929\u5929\u770b Yii \u6e90\u7801\uff0c\u611f\u89c9\u8fd8\u662f\u975e\u5e38\u723d\u7684\u3002\u672c\u6587\u5c06\u8981\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Yii \u5185\u7f6e\u7684\u65b9\u6cd5\uff0c\u8f93\u51fa\u6587\u4ef6\u3001\u6d41\u3001\u5b57\u7b26\u4e32\u4e3a\u4e0b\u8f7d\u54cd\u5e94\u3002\n\u901a\u8fc7\u67e5\u770b yii\\web\\Response \u6e90\u7801\u53ef\u77e5\uff0c\u5176\u63d0\u4f9b\u5982\u4e0b\u65b9\u6cd5\uff1a\npublic function sendFile($filePath, $attachmentName = null, $options = []); public function sendContentAsFile($content, $attachmentName, $options = []); public function sendStreamAsFile($handle, $attachmentName, $options = []); \u90a3\u4e48\u5982\u4f55\u5728\u63a7\u5236\u5668\u5185\u8c03\u7528\u6b64\u65b9\u6cd5\u8f93\u51fa\u5462\uff1f\n\u4e24\u79cd\u65b9\u6848\uff1a\npublic function actionIndex() { return \\Yii::$app-&gt;getResponse()-&gt;sendFile(...); \/\/ `sendFile` \u8fd4\u56de self } \u6216\npublic function actionIndex() { \\Yii::$app-&gt;getResponse()-&gt;sendFile(...); return null; \/\/ or `return;` or do nothing. }  \u6839\u636e yii\\web\\Application::handleRequest \u53ef\u77e5\uff1aYii \u4f1a\u5224\u65ad action \u8fd4\u56de\u503c\u3002\n\u82e5\u662f yii\\web\\Response \u5b9e\u4f8b\u5219\u76f4\u63a5\u8fd4\u56de\u7ed9 \\yii\\base\\Application::run \u51fd\u6570\u8fdb\u884c\u8f93\u51fa\u3002\n\u5426\u5219\u5224\u65ad\u5176\u662f\u5426\u4e3a null\uff0c\u82e5\u662f\uff0c\u5219\u4ec0\u4e48\u90fd\u4e0d\u505a\uff1b\u5219\u6211\u4eec\u8bbe\u7f6e\u7684 sendFile \u5c31\u4f1a\u6709\u6548\u3002\n ","permalink":"https:\/\/wi1dcard.dev\/posts\/yii2-response-send-file\/","summary":"\u6700\u8fd1\u4e3a\u4e86\u5c3d\u53ef\u80fd\u4f18\u96c5\u5730\u5b9e\u73b0\u4ea7\u54c1\u9700\u6c42\uff0c\u5929\u5929\u770b Yii \u6e90\u7801\uff0c\u611f\u89c9\u8fd8\u662f\u975e\u5e38\u723d\u7684\u3002\u672c\u6587\u5c06\u8981\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Yii \u5185\u7f6e\u7684\u65b9\u6cd5\uff0c\u8f93\u51fa\u6587\u4ef6\u3001\u6d41\u3001\u5b57\u7b26\u4e32\u4e3a\u4e0b\u8f7d\u54cd\u5e94\u3002\n\u901a\u8fc7\u67e5\u770b yii\\web\\Response \u6e90\u7801\u53ef\u77e5\uff0c\u5176\u63d0\u4f9b\u5982\u4e0b\u65b9\u6cd5\uff1a\npublic function sendFile($filePath, $attachmentName = null, $options = []); public function sendContentAsFile($content, $attachmentName, $options = []); public function sendStreamAsFile($handle, $attachmentName, $options = []); \u90a3\u4e48\u5982\u4f55\u5728\u63a7\u5236\u5668\u5185\u8c03\u7528\u6b64\u65b9\u6cd5\u8f93\u51fa\u5462\uff1f","title":"Yii2 \u8f93\u51fa\u6587\u4ef6\u4e0b\u8f7d\u54cd\u5e94"},{"content":"\u4e0a\u6587\u8bb2\u89e3\u5173\u4e8e\u5982\u4f55\u6620\u5c04 Action\uff0c\u672c\u6587\u8bb2\u89e3\u5982\u4f55\u6620\u5c04 Controller\u3002\n0x00 \u5b9e\u73b0 \u9996\u5148\uff0c\u5728\u4f60\u7684 Module \u91cc\uff0c\u5b9a\u4e49\u4e00\u4e2a $controllerRedirectMap \u53d8\u91cf\u3002\npublic $controllerRedirectMap = []; \u91cd\u5199 createControllerByID \u65b9\u6cd5\u3002\npublic function createControllerByID($id) { if(isset($this-&gt;controllerRedirectMap[$id])) { $id = $this-&gt;controllerRedirectMap[$id]; } return parent::createControllerByID($id); } 0x01 \u7528\u6cd5 public $controllerRedirectMap = [ &#39;foo&#39; =&gt; &#39;bar&#39; \/\/ \u8bbf\u95ee `module\/foo\/index` \u5c06\u4f1a\u88ab\u91cd\u5b9a\u5411\u81f3 `module\/bar\/index`  &#39;foo\/bar&#39; =&gt; &#39;bar\/foo&#39; \/\/ \u8bbf\u95ee `module\/foo\/bar\/index` \u5c06\u4f1a\u88ab\u91cd\u5b9a\u5411\u81f3 `module\/bar\/foo\/index` ]; 0x02 \u611f\u60f3 \u4e00\u53e3\u6c14\u5199\u4e09\u7bc7\u5173\u4e8e Yii2 \u7684\u535a\u6587\uff0c\u7b97\u662f\u5bf9\u81ea\u5df1\u8fd1\u671f\u9879\u76ee\u4e2d\u7528\u5230 Yii \u4ee5\u6765\u7684\u6280\u5de7\u5c0f\u7ed3\u5427\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/yii2-redirect-controller-in-module\/","summary":"\u4e0a\u6587\u8bb2\u89e3\u5173\u4e8e\u5982\u4f55\u6620\u5c04 Action\uff0c\u672c\u6587\u8bb2\u89e3\u5982\u4f55\u6620\u5c04 Controller\u3002\n0x00 \u5b9e\u73b0 \u9996\u5148\uff0c\u5728\u4f60\u7684 Module \u91cc\uff0c\u5b9a\u4e49\u4e00\u4e2a $controllerRedirectMap \u53d8\u91cf\u3002\npublic $controllerRedirectMap = []; \u91cd\u5199 createControllerByID \u65b9\u6cd5\u3002\npublic function createControllerByID($id) { if(isset($this-&gt;controllerRedirectMap[$id])) { $id = $this-&gt;controllerRedirectMap[$id]; } return parent::createControllerByID($id); } 0x01 \u7528\u6cd5 public $controllerRedirectMap = [ &#39;foo&#39; =&gt; &#39;bar&#39; \/\/ \u8bbf\u95ee `module\/foo\/index` \u5c06\u4f1a\u88ab\u91cd\u5b9a\u5411\u81f3 `module\/bar\/index`  &#39;foo\/bar&#39; =&gt; &#39;bar\/foo&#39; \/\/ \u8bbf\u95ee `module\/foo\/bar\/index` \u5c06\u4f1a\u88ab\u91cd\u5b9a\u5411\u81f3 `module\/bar\/foo\/index` ]; 0x02 \u611f\u60f3 \u4e00\u53e3\u6c14\u5199\u4e09\u7bc7\u5173\u4e8e Yii2 \u7684\u535a\u6587\uff0c\u7b97\u662f\u5bf9\u81ea\u5df1\u8fd1\u671f\u9879\u76ee\u4e2d\u7528\u5230 Yii \u4ee5\u6765\u7684\u6280\u5de7\u5c0f\u7ed3\u5427\u3002","title":"Yii2 \u5728\u6a21\u5757\u5185\u6620\u5c04 Controller \u5230\u5176\u5b83\u63a7\u5236\u5668"},{"content":"\u672c\u6587\u8bb2\u89e3\uff1a\u5982\u4f55\u628a\u63a7\u5236\u5668\u5185\u7684\u4efb\u610f\u4e00\u4e2a Action \u6620\u5c04\u5230\u53e6\u4e00\u4e2a Action\u3002\n0x00 \u51c6\u5907  Yii ^ 2.0.7  0x01 \u4ee3\u7801 \u9996\u5148\u5b9a\u4e49\u4e00\u4e2a RedirectAction \u7c7b\u3002\nclass RedirectAction { protected $actionId; public function __construct($actionId) { $this-&gt;actionId = $actionId; } public function __invoke($id, \\yii\\base\\Controller $controller) { return $controller-&gt;createAction($this-&gt;actionId); } } \u63a5\u7740\u5728\u63a7\u5236\u5668\u5185\u91cd\u5199\u5b9e\u73b0 actions() \u65b9\u6cd5\uff0c\u7528\u4e8e\u6620\u5c04 Action ID =&gt; \u5b9e\u9645\u7684\u52a8\u4f5c\u3002\nclass Controller { public function actions() { return [ &#39;foo&#39; =&gt; new RedirectAction(&#39;bar&#39;), \/\/ \u8bbf\u95ee `module\/controller\/foo` \u5c06\u4f1a\u88ab\u91cd\u5b9a\u5411\u81f3 `actionBar` \u65b9\u6cd5  \/\/ ...  ]; } public function actionBar() { return &#39;bar&#39;; } } \u5b8c\u6210\u3002\n0xFF \u611f\u60f3 \u56de\u5934\u518d\u770b Laravel\uff0c\u771f\u5fc3\u611f\u6fc0 Laravel \u7684\u81ea\u5b9a\u4e49\u8def\u7531&hellip;\n","permalink":"https:\/\/wi1dcard.dev\/posts\/yii2-redirect-action-in-controller\/","summary":"\u672c\u6587\u8bb2\u89e3\uff1a\u5982\u4f55\u628a\u63a7\u5236\u5668\u5185\u7684\u4efb\u610f\u4e00\u4e2a Action \u6620\u5c04\u5230\u53e6\u4e00\u4e2a Action\u3002\n0x00 \u51c6\u5907  Yii ^ 2.0.7  0x01 \u4ee3\u7801 \u9996\u5148\u5b9a\u4e49\u4e00\u4e2a RedirectAction \u7c7b\u3002\nclass RedirectAction { protected $actionId; public function __construct($actionId) { $this-&gt;actionId = $actionId; } public function __invoke($id, \\yii\\base\\Controller $controller) { return $controller-&gt;createAction($this-&gt;actionId); } } \u63a5\u7740\u5728\u63a7\u5236\u5668\u5185\u91cd\u5199\u5b9e\u73b0 actions() \u65b9\u6cd5\uff0c\u7528\u4e8e\u6620\u5c04 Action ID =&gt; \u5b9e\u9645\u7684\u52a8\u4f5c\u3002","title":"Yii2 \u5728\u63a7\u5236\u5668\u5185\u6620\u5c04 Action \u5230\u5176\u5b83\u52a8\u4f5c"},{"content":"\u7c7b\u4f3c Laravel \u7684\u6548\u679c\uff1a\u76f4\u63a5 return \u6570\u7ec4\u8f93\u51fa JSON \u54cd\u5e94\u3002\u529e\u6cd5\u6709\u5f88\u591a\uff0c\u76ee\u524d\u6211\u627e\u5230\u7684\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5982\u4e0b\u3002\n\/** * Enable JSON response if app returns Array or Object * * @return void *\/ protected function enableJsonResponse() { $this-&gt;response-&gt;on(\\yii\\web\\Response::EVENT_BEFORE_SEND, function ($event) { \/** @var \\yii\\web\\Response $response *\/ $response = $event-&gt;sender; if (is_array($response-&gt;data) || is_object($response-&gt;data)) { $response-&gt;format = \\yii\\web\\Response::FORMAT_JSON; } } ); } \u6216\u8005\u5728\u914d\u7f6e\u5185\u5b9a\u4e49\u4e5f\u53ef\u4ee5\uff1a\n&#39;response&#39; =&gt; [ &#39;on beforeSend&#39; =&gt; function ($event) { \/\/ \u56de\u8c03\u51fd\u6570\u4ee3\u7801\u5982\u4e0a\uff0c\u540c\u7406  } \/\/ ... ] ","permalink":"https:\/\/wi1dcard.dev\/posts\/yii2-return-array-in-controller\/","summary":"\u7c7b\u4f3c Laravel \u7684\u6548\u679c\uff1a\u76f4\u63a5 return \u6570\u7ec4\u8f93\u51fa JSON \u54cd\u5e94\u3002\u529e\u6cd5\u6709\u5f88\u591a\uff0c\u76ee\u524d\u6211\u627e\u5230\u7684\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u5982\u4e0b\u3002\n\/** * Enable JSON response if app returns Array or Object * * @return void *\/ protected function enableJsonResponse() { $this-&gt;response-&gt;on(\\yii\\web\\Response::EVENT_BEFORE_SEND, function ($event) { \/** @var \\yii\\web\\Response $response *\/ $response = $event-&gt;sender; if (is_array($response-&gt;data) || is_object($response-&gt;data)) { $response-&gt;format = \\yii\\web\\Response::FORMAT_JSON; } } ); } \u6216\u8005\u5728\u914d\u7f6e\u5185\u5b9a\u4e49\u4e5f\u53ef\u4ee5\uff1a","title":"Yii2 \u5141\u8bb8\u63a7\u5236\u5668\u5185\u76f4\u63a5\u8fd4\u56de\u6570\u7ec4"},{"content":"PHPer \u4eec\u5e94\u8be5\u90fd\u77e5\u9053 str_replace \u51fd\u6570\uff0c\u800c\u5982\u4f55\u4f7f\u7528\u6570\u7ec4\u6279\u91cf\u66ff\u6362\u67d0\u5b57\u7b26\u4e32\u5185\u7684\u5b50\u4e32\uff0c\u8fd9\u91cc\u6709\u4e2a\u9a9a\u64cd\u4f5c\u3002\n\u8bdd\u4e0d\u591a\u8bf4\uff0c\u76f4\u63a5\u4e0a\u4ee3\u7801\uff1a\n$map = [ &#39;foo&#39; =&gt; &#39;bar&#39;, \/\/ ... ]; $str = str_replace(array_keys($map), array_values($map), $str); ","permalink":"https:\/\/wi1dcard.dev\/posts\/php-str-replace-in-associative-array\/","summary":"PHPer \u4eec\u5e94\u8be5\u90fd\u77e5\u9053 str_replace \u51fd\u6570\uff0c\u800c\u5982\u4f55\u4f7f\u7528\u6570\u7ec4\u6279\u91cf\u66ff\u6362\u67d0\u5b57\u7b26\u4e32\u5185\u7684\u5b50\u4e32\uff0c\u8fd9\u91cc\u6709\u4e2a\u9a9a\u64cd\u4f5c\u3002\n\u8bdd\u4e0d\u591a\u8bf4\uff0c\u76f4\u63a5\u4e0a\u4ee3\u7801\uff1a\n$map = [ &#39;foo&#39; =&gt; &#39;bar&#39;, \/\/ ... ]; $str = str_replace(array_keys($map), array_values($map), $str); ","title":"PHP \u6279\u91cf\u66ff\u6362\u5b57\u7b26\u4e32"},{"content":"\u8bb2\u4e2a PHP \u7684\u9a9a\u64cd\u4f5c\u3002\u8bba\u5982\u4f55\u5b9e\u73b0\uff1a\u628a\u4e8c\u7ef4\u6570\u7ec4\u5185\u67d0\u4e8c\u7ef4\u5143\u7d20\u7684\u503c\uff0c\u5355\u72ec\u63d0\u51fa\u6765\u7ec4\u6210\u4e00\u7ef4\u6570\u7ec4\u3002\n0x00 \u4f20\u7edf\u64cd\u4f5c $pieces = []; foreach($whole as $item) { $pieces[] = $item[&#39;foo&#39;]; } return $pieces; 0x01 \u9a9a\u64cd\u4f5c return array_map( function ($item) { return $item[&#39;foo&#39;]; }, $whole ); \u7701\u6389\u4e24\u4e2a\u53d8\u91cf\uff08$pieces\u3001$item\uff09\uff0c\u5bf9\u4e8e\u4e1a\u52a1\u903b\u8f91\u6bd4\u8f83\u590d\u6742\u7684\u4f4d\u7f6e\uff0c\u7701\u4e00\u4e2a\u53d8\u91cf\u8bf4\u4e0d\u5b9a\u5c31\u5c11\u6b7b\u5341\u4e2a\u8111\u7ec6\u80de&hellip;\n PHP \u5185\uff0c\u51fd\u6570\u5185\u90e8\u53d8\u91cf\u6ca1\u6709\u4f5c\u7528\u57df\u4e4b\u5206\uff0c\u53ea\u6709\u51fa\u51fd\u6570\u540e\u624d\u4f1a\u9500\u6bc1\u3002\u6240\u4ee5 $item \u5728\u533f\u540d\u51fd\u6570\u5185\u662f\u5916\u90e8\u65e0\u6cd5\u8bbf\u95ee\u7684\u3002\n 0x02 \u62d3\u5c55 array_map \u5176\u5b9e\u8fd8\u6709\u4e0d\u5c11\u7528\u9014\uff0c\u9700\u8981\u904d\u5386\u6570\u7ec4\u6bcf\u4e2a\u5143\u7d20\u7684\u300c\u503c\u300d\u7684\u65f6\u5019\uff0c\u90fd\u53ef\u4ee5\u6d3e\u4e0a\u7528\u573a\u3002\n\u4f46\u9700\u8981\u904d\u5386 Key =&gt; Value \u5f62\u5f0f\u7684\u5173\u8054\u6570\u7ec4\uff0c\u8be5\u600e\u4e48\u64cd\u4f5c\u5462\uff1f\nreturn array_map( function callback($k, $v) { ... }, array_keys($array), $array ); \u641e\u5b9a\u3002\n0x03 \u53c2\u8003 PHP \u6587\u6863 - array_map\n0xFF \u611f\u8a00 \u4e8b\u5b9e\u4e0a\uff0carray_map \u6709\u70b9\u50cf JavaScript \u91cc\u7684 array.forEach\uff0c.NET \u91cc\u7684 List.Select\u3002\n\u4e0d\u8fc7\u9057\u61be\u7684\u662f\uff0c\u6ca1\u6709 JS \u90a3\u4e48\u9a9a\u7684\u95ed\u5305\u3001\u4e5f\u6ca1\u6709 C# \u90a3\u4e48\u540a\u7684 lambda \/ linq\uff0c\u771f\u662f\u84dd\u7626\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-array-map-instead-of-foreach\/","summary":"\u8bb2\u4e2a PHP \u7684\u9a9a\u64cd\u4f5c\u3002\u8bba\u5982\u4f55\u5b9e\u73b0\uff1a\u628a\u4e8c\u7ef4\u6570\u7ec4\u5185\u67d0\u4e8c\u7ef4\u5143\u7d20\u7684\u503c\uff0c\u5355\u72ec\u63d0\u51fa\u6765\u7ec4\u6210\u4e00\u7ef4\u6570\u7ec4\u3002\n0x00 \u4f20\u7edf\u64cd\u4f5c $pieces = []; foreach($whole as $item) { $pieces[] = $item[&#39;foo&#39;]; } return $pieces; 0x01 \u9a9a\u64cd\u4f5c return array_map( function ($item) { return $item[&#39;foo&#39;]; }, $whole ); \u7701\u6389\u4e24\u4e2a\u53d8\u91cf\uff08$pieces\u3001$item\uff09\uff0c\u5bf9\u4e8e\u4e1a\u52a1\u903b\u8f91\u6bd4\u8f83\u590d\u6742\u7684\u4f4d\u7f6e\uff0c\u7701\u4e00\u4e2a\u53d8\u91cf\u8bf4\u4e0d\u5b9a\u5c31\u5c11\u6b7b\u5341\u4e2a\u8111\u7ec6\u80de&hellip;","title":"PHP \u4f7f\u7528 array_map \u66ff\u4ee3 foreach"},{"content":"\u8fd9\u4e24\u5929\u53c8\u5728\u6298\u817e\u7f16\u8f91\u5668\uff0c\u65e9\u4e0a\u521a\u66f4\u65b0\u4e86\u5173\u4e8e VSCode \u7684\u6700\u65b0\u914d\u7f6e\u3002\n\u4ece\u63a5\u89e6 Markdown \u5230\u73b0\u5728\uff0c\u5dee\u4e0d\u591a\u4e00\u5e74\uff0c\u6700\u5f00\u59cb\u8bb0\u4e0d\u4f4f\u683c\u5f0f\u3001\u5230\u73b0\u5728\u9a7e\u8f7b\u5c31\u719f\u3002\n\u6700\u65e9\u7684\u65f6\u5019\uff0c\u5165\u95e8 MD \u9009\u4e86\u5f88\u4e45\u7684\u7f16\u8f91\u5668\uff0c\u4ece\u5404\u7c7b\u5728\u7ebf\u7f16\u8f91\u4e00\u8def\u64b8\u5230 MacDown\uff0c\u90a3\u4e2a\u65f6\u5019\u9009\u7f16\u8f91\u5668\u7684\u552f\u4e00\u6807\u51c6\u5c31\u662f\uff1a\u9884\u89c8\u4e00\u5b9a\u8981\u5f3a\u5927\u725b\u903c\ud83d\ude02\u3002\n\u540e\u6765\u628a MD \u4f5c\u4e3a\u4ee3\u7801\u6587\u6863\u6807\u914d\uff0c\u5c31\u5f00\u59cb\u5c1d\u8bd5\u7528 VSCode \u5199 MD\uff0c\u4e5f\u6162\u6162\u603b\u7ed3\u51fa\u4e86\u4e00\u4e9b\u4f18\u52a3\uff1a\n VSCode \u652f\u6301\u4ee3\u7801\u9ad8\u4eae\u6e32\u67d3\uff0cMacDown \u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u914d\u7f6e\u5404\u7c7b\u6e32\u67d3\u9009\u9879\u3001\u81ea\u5b9a\u4e49 CSS\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u56de\u8f66\u81ea\u52a8\u8865\u5168\u5217\u8868 - \/ *\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u5bfc\u51fa PDF\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002  \u4f46\u662f\uff01\u5c31\u50cf\u6211\u5f88\u65e9\u4e4b\u524d\u5728 \u63a8\u8350 VSCode \u7684\u535a\u6587 \u91cc\u8bf4\u7684\u90a3\u6837\uff1a\n VS Code \u5f3a\u5927\u4e4b\u5904\u4e0d\u5728\u4e8e\u672c\u8eab\uff0c\u800c\u5728\u4e8e\u5f3a\u5927\u7684\u53ef\u6269\u5c55\u6027\u3001\u4ee5\u53ca\u65e5\u6e10\u58ee\u5927\u7684\u63d2\u4ef6\u5546\u5e97\u3002\n \u8fd9\u51e0\u5929\u4e00\u6298\u817e\u53d1\u73b0&hellip; \u4ee5\u4e0a\u529f\u80fd\u5168\u90e8\u6709\u63d2\u4ef6\u5b9e\u73b0\u4e86&hellip;\n\u800c\u5c31\u76ee\u524d\u6765\u8bf4\uff0c\u6211\u5bf9 Markdown \u7684\u719f\u7ec3\u7a0b\u5ea6\u57fa\u672c\u4e0a\u53ef\u4ee5\u8131\u79bb\u9884\u89c8\uff0c\u53ea\u8981\u6709\u4e2a\u9ad8\u4eae\u3001\u751a\u81f3\u4e0d\u9700\u8981\u8865\u5168\u5c31\u53ef\u4ee5\u3002\u518d\u52a0\u4e0a\u8f7b\u5fae\u5f3a\u8feb\u771f\u3001\u70ed\u7231\u6781\u7b80\u4e3b\u4e49\uff0c\u66f4\u662f \u591a\u4e00 App\uff0c\u4e0d\u5982\u5c11\u4e00 App\u3002\n\u4e8e\u662f\uff0c\u6253\u7b97\u8ddf MacDown \u544a\u522b\u4e86\uff0c\u4e34\u522b\u5199\u4e2a\u6587\u7ae0\u7eaa\u5ff5\u5b83\u4e00\u5e74\u4ee5\u6765\u5bf9\u6211\u5b66\u4e60 Markdown \u7684\u5e2e\u52a9\uff0c\u529f\u4e0d\u53ef\u6ca1\u3002\n\u5408\u4e2a\u5f71\uff1a\nGoodbye, MacDown.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/say-goodbye-to-macdown\/","summary":"\u8fd9\u4e24\u5929\u53c8\u5728\u6298\u817e\u7f16\u8f91\u5668\uff0c\u65e9\u4e0a\u521a\u66f4\u65b0\u4e86\u5173\u4e8e VSCode \u7684\u6700\u65b0\u914d\u7f6e\u3002\n\u4ece\u63a5\u89e6 Markdown \u5230\u73b0\u5728\uff0c\u5dee\u4e0d\u591a\u4e00\u5e74\uff0c\u6700\u5f00\u59cb\u8bb0\u4e0d\u4f4f\u683c\u5f0f\u3001\u5230\u73b0\u5728\u9a7e\u8f7b\u5c31\u719f\u3002\n\u6700\u65e9\u7684\u65f6\u5019\uff0c\u5165\u95e8 MD \u9009\u4e86\u5f88\u4e45\u7684\u7f16\u8f91\u5668\uff0c\u4ece\u5404\u7c7b\u5728\u7ebf\u7f16\u8f91\u4e00\u8def\u64b8\u5230 MacDown\uff0c\u90a3\u4e2a\u65f6\u5019\u9009\u7f16\u8f91\u5668\u7684\u552f\u4e00\u6807\u51c6\u5c31\u662f\uff1a\u9884\u89c8\u4e00\u5b9a\u8981\u5f3a\u5927\u725b\u903c\ud83d\ude02\u3002\n\u540e\u6765\u628a MD \u4f5c\u4e3a\u4ee3\u7801\u6587\u6863\u6807\u914d\uff0c\u5c31\u5f00\u59cb\u5c1d\u8bd5\u7528 VSCode \u5199 MD\uff0c\u4e5f\u6162\u6162\u603b\u7ed3\u51fa\u4e86\u4e00\u4e9b\u4f18\u52a3\uff1a\n VSCode \u652f\u6301\u4ee3\u7801\u9ad8\u4eae\u6e32\u67d3\uff0cMacDown \u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u914d\u7f6e\u5404\u7c7b\u6e32\u67d3\u9009\u9879\u3001\u81ea\u5b9a\u4e49 CSS\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u56de\u8f66\u81ea\u52a8\u8865\u5168\u5217\u8868 - \/ *\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002 MacDown \u652f\u6301\u5bfc\u51fa PDF\uff0cVSCode \u539f\u751f\u4e0d\u652f\u6301\u3002  \u4f46\u662f\uff01\u5c31\u50cf\u6211\u5f88\u65e9\u4e4b\u524d\u5728 \u63a8\u8350 VSCode \u7684\u535a\u6587 \u91cc\u8bf4\u7684\u90a3\u6837\uff1a","title":"\u5bf9 MacDown \u8bf4\u518d\u89c1"},{"content":"PHP Storm \u56e0\u529f\u80fd\u5f3a\u5927\u88ab PHPer \u4eec\u6240\u719f\u77e5\uff0c\u4f46\u81ea\u8eab\u529f\u80fd\u6108\u53d1\u5f3a\u5927\u5e26\u6765\u7684\u95ee\u9898\u4e5f\u540c\u6837\u660e\u663e\uff1a\u529f\u80fd\u81c3\u80bf\uff0f\u542f\u52a8\u7f13\u6162\uff0f\u5185\u5b58\u5360\u7528\u9ad8\u7b49\u3002VS Code \u7ecf\u8fc7\u51e0\u5e74\u7684\u53d1\u5c55\u7b97\u662f\u540e\u8d77\u4e4b\u79c0\uff0c\u5360\u9886\u4e86\u4e00\u90e8\u5206\u5c0f\u4f17\u5e02\u573a\u3002\n\u5c1d\u8bd5\u53d1\u73b0\uff0c\u901a\u8fc7\u6df1\u5ea6\u914d\u7f6e\uff0cVS Code \u7f16\u5199 PHP \u4ee3\u7801\u7684\u4f53\u9a8c\u5b8c\u5168\u4e0d\u4e9a\u4e8e PHP Storm\u3002\u6545\u4eca\u5929\u4e3a\u5927\u5bb6\u4ecb\u7ecd\uff1a\u6765\u81ea\u5fae\u8f6f\u7684\u9a9a\u64cd\u4f5c \u2014\u2014 VS Code\u3002\n\u66f4\u65b0\uff082019 \u5e74 4 \u6708 11 \u65e5\uff09 \u7531\u4e8e Settings \u5185\u5305\u542b\u654f\u611f\u4fe1\u606f\uff0c\u56e0\u6b64 Gist \u94fe\u63a5\u5df2\u79fb\u9664\u3002\n\u66f4\u65b0\uff082018 \u5e74 7 \u6708 10 \u65e5\uff09 \u6700\u8fd1\u53d1\u73b0\u4e2a\u65b0\u63d2\u4ef6\uff0c\u652f\u6301\u540c\u6b65 VSCode \u8bbe\u7f6e\uff0c\u540d\u53eb\u300cSettings Sync\u300d\uff0c\u56e0\u6b64\u6211\u4f7f\u7528\u6b64\u63d2\u4ef6\u628a\u914d\u7f6e\u5b8c\u5168\u516c\u5f00\u81f3 GitHub Gist \u4ee5\u4f9b\u53c2\u8003\u3002\u5b89\u88c5 \u76f4\u63a5\u8bbf\u95ee\u5b98\u7f51\uff1ahttps:\/\/code.visualstudio.com\n\u63d2\u4ef6 VS Code \u5f3a\u5927\u4e4b\u5904\u4e0d\u5728\u4e8e\u672c\u8eab\uff0c\u800c\u5728\u4e8e\u5f3a\u5927\u7684\u53ef\u6269\u5c55\u6027\u3001\u4ee5\u53ca\u65e5\u6e10\u58ee\u5927\u7684\u63d2\u4ef6\u5546\u5e97\u3002\u8fd9\u91cc\u5217\u51fa\u6211\u7528\u5230\u7684\u51e0\u4e2a\u63d2\u4ef6\uff1a\n One Dark Pro\uff1a\u4e00\u6b3e\u6e90\u81ea Atom \u7684\u4e3b\u9898\uff1b Composer\uff1a\u7528\u4e8e\u652f\u6301\u5728 Code \u547d\u4ee4\u7a97\u53e3\uff08\u2b06\ufe0f+Command+P\uff09\u5feb\u6377\u8f93\u5165 Composer \u547d\u4ee4\uff1b Laravel 5 Snippets\uff08Winnie Lin\uff09\uff1a\u5305\u542b\u5e38\u7528 Facade \u7684 Snippets\uff1b Laravel Artisan\uff1a\u7528\u4e8e\u652f\u6301\u5728 Code \u547d\u4ee4\u7a97\u53e3\u5feb\u6377\u8f93\u5165 Artisan \u547d\u4ee4\uff1b Path Intellisense\uff1a\u667a\u80fd\u8865\u5168\u6587\u4ef6\u8def\u5f84\uff1b PHP Debug\uff1a\u914d\u5408 XDebug \u5b9e\u73b0\u5f3a\u5927\u7684\u8c03\u8bd5\u529f\u80fd\uff1b PHP DocBlocker\uff1a\u667a\u80fd\u8865\u5168 PHP Doc\uff1b PHP Intelephense\uff1a\u622a\u81f3\u76ee\u524d\u6211\u8ba4\u4e3a\u6700\u597d\u7684 PHP \u81ea\u52a8\u8865\u5168\u63d2\u4ef6\uff1b vscode-icons\uff1a\u66ff\u6362\u5de6\u4fa7\u8d44\u6e90\u7ba1\u7406\u680f\u7684\u56fe\u6807\u3002  \u914d\u7f6e \u88c5\u5b8c\u63d2\u4ef6\u9700\u8981\u8c03\u6574\u90e8\u5206\u914d\u7f6e\u5b9e\u73b0\u81ea\u5b9a\u4e49\u90e8\u5206\u529f\u80fd\u548c\u754c\u9762\uff0c\u4f7f\u7528 Command+, \u6253\u5f00\u8bbe\u7f6e\u9875\uff0c\u5728\u53f3\u4fa7\u8f93\u5165\u7528\u6237\u914d\u7f6e\u66ff\u6362\u539f\u6709\u7cfb\u7edf\u914d\u7f6e\u5373\u53ef\u3002\u5206\u4eab\u6211\u7684\u914d\u7f6e\uff1a\n{ &#34;workbench.colorTheme&#34;: &#34;One Dark Pro&#34;, \/\/ \u4e3b\u9898 &#34;editor.formatOnType&#34;: true, \/\/ \u6253\u5b57\u65f6\u81ea\u52a8\u7f8e\u5316\u4ee3\u7801 &#34;editor.autoIndent&#34;: true, \/\/ \u81ea\u52a8\u8c03\u6574\u7f29\u8fdb &#34;editor.formatOnPaste&#34;: true, \/\/ \u7c98\u8d34\u65f6\u81ea\u52a8\u7f8e\u5316\u4ee3\u7801 &#34;editor.fontSize&#34;: 14, \/\/ \u5b57\u4f53\u5927\u5c0f &#34;editor.lineHeight&#34;: 26, \/\/ \u884c\u9ad8 &#34;editor.fontFamily&#34;: &#34;Monaco&#34;, \/\/ \u7f16\u8f91\u5668\u5b57\u4f53 &#34;php.validate.enable&#34;: true, \/\/ \u6253\u5f00Code\u81ea\u5e26\u7684\u81ea\u52a8\u68c0\u67e5\u4ee3\u7801 &#34;php.validate.executablePath&#34;: &#34;php&#34;, \/\/ \u914d\u7f6ephp\u6267\u884c\u6587\u4ef6\u7684\u8def\u5f84 &#34;files.autoSave&#34;: &#34;onFocusChange&#34;, \/\/ \u7f16\u8f91\u5668\u79bb\u5f00\u7126\u70b9\u81ea\u52a8\u4fdd\u5b58 &#34;php.suggest.basic&#34;: false, \/\/ \u5173\u95edCode\u81ea\u5e26\u7684\u81ea\u52a8\u8865\u5168(\u6709\u63d2\u4ef6) &#34;editor.snippetSuggestions&#34;: &#34;inline&#34;, \/\/ Laravel Snippets\u5728\u81ea\u52a8\u8865\u5168\u5217\u8868\u4e2d\u7684\u6392\u5e8f &#34;workbench.iconTheme&#34;: &#34;vscode-icons&#34; \/\/ \u56fe\u6807 } 2018.5.13 \u66f4\u65b0\uff1a\n{ \/\/\u5e38\u7528 &#34;workbench.colorTheme&#34;: &#34;One Dark Pro&#34;, &#34;workbench.iconTheme&#34;: &#34;vscode-icons&#34;, &#34;window.zoomLevel&#34;: 0, &#34;explorer.confirmDelete&#34;: false, &#34;files.autoSave&#34;: &#34;onFocusChange&#34;, \/\/\u7f16\u8f91\u5668 &#34;editor.formatOnType&#34;: true, &#34;editor.formatOnPaste&#34;: true, &#34;editor.autoIndent&#34;: true, &#34;editor.fontSize&#34;: 14, &#34;editor.lineHeight&#34;: 26, &#34;editor.fontFamily&#34;: &#34;Monaco&#34;, &#34;editor.snippetSuggestions&#34;: &#34;inline&#34;, \/\/PHP &#34;php.suggest.basic&#34;: false, &#34;php.validate.enable&#34;: true, &#34;php.validate.executablePath&#34;: &#34;php&#34;, \/\/C# &#34;csharp.format.enable&#34;: false, &#34;csharp.referencesCodeLens.enabled&#34;: false, \/\/Python &#34;python.pythonPath&#34;: &#34;python3&#34;, \/\/\u7b2c\u4e09\u65b9\u63d2\u4ef6 &#34;code-runner.saveAllFilesBeforeRun&#34;: true, &#34;phpfmt.detect_indent&#34;: true, &#34;phpfmt.visibility_order&#34;: true } \u81ea\u5b9a\u4e49 Snippets \u6253\u5f00\u4e3b\u83dc\u5355-&gt;\u9996\u9009\u9879-&gt;\u7528\u6237\u4ee3\u7801\u7247\u6bb5\uff0c\u8f93\u5165\uff1aPHP\uff0c\u5373\u53ef\u8df3\u5230\u81ea\u5b9a\u4e49 Snippets \u9875\u9762\uff0c\u5206\u4eab\u6211\u7684\u914d\u7f6e\uff1a\n{ &#34;Laravel Action&#34;:{ &#34;prefix&#34;: &#34;action&#34;, &#34;description&#34;: &#34;Action in Laravel Controller&#34;, &#34;body&#34;: [ &#34;public function ${1:action}(Request \\\\$request) {&#34;, &#34;\\t$0&#34;, &#34;}&#34; ] } } \u5173\u4e8e\u81ea\u5b9a\u4e49 Snippets \u7684\u8be6\u7ec6\u4ecb\u7ecd\u53ef\u53c2\u8003\u6b64\u6587\uff1a\u8ddf\u6211\u4e00\u8d77\u5728 Visual Studio Code \u6dfb\u52a0\u81ea\u5b9a\u4e49 snippet\uff08\u4ee3\u7801\u6bb5\uff09\uff0c\u9644\u8be6\u7ec6\u914d\u7f6e\n\u5feb\u6377\u952e VS Code for Mac \u5e38\u7528\u5feb\u6377\u952e\u5217\u8868\n\u6700\u7ec8\u6548\u679c \u4eca\u665a\u4f1a\u8bae\u684c\uff0c\u4e0d\u8981\u9519\u8fc7\u3002\uff0f\u659c\u773c\u7b11\n","permalink":"https:\/\/wi1dcard.dev\/posts\/proud-to-use-vscode\/","summary":"PHP Storm \u56e0\u529f\u80fd\u5f3a\u5927\u88ab PHPer \u4eec\u6240\u719f\u77e5\uff0c\u4f46\u81ea\u8eab\u529f\u80fd\u6108\u53d1\u5f3a\u5927\u5e26\u6765\u7684\u95ee\u9898\u4e5f\u540c\u6837\u660e\u663e\uff1a\u529f\u80fd\u81c3\u80bf\uff0f\u542f\u52a8\u7f13\u6162\uff0f\u5185\u5b58\u5360\u7528\u9ad8\u7b49\u3002VS Code \u7ecf\u8fc7\u51e0\u5e74\u7684\u53d1\u5c55\u7b97\u662f\u540e\u8d77\u4e4b\u79c0\uff0c\u5360\u9886\u4e86\u4e00\u90e8\u5206\u5c0f\u4f17\u5e02\u573a\u3002\n\u5c1d\u8bd5\u53d1\u73b0\uff0c\u901a\u8fc7\u6df1\u5ea6\u914d\u7f6e\uff0cVS Code \u7f16\u5199 PHP \u4ee3\u7801\u7684\u4f53\u9a8c\u5b8c\u5168\u4e0d\u4e9a\u4e8e PHP Storm\u3002\u6545\u4eca\u5929\u4e3a\u5927\u5bb6\u4ecb\u7ecd\uff1a\u6765\u81ea\u5fae\u8f6f\u7684\u9a9a\u64cd\u4f5c \u2014\u2014 VS Code\u3002\n\u66f4\u65b0\uff082019 \u5e74 4 \u6708 11 \u65e5\uff09 \u7531\u4e8e Settings \u5185\u5305\u542b\u654f\u611f\u4fe1\u606f\uff0c\u56e0\u6b64 Gist \u94fe\u63a5\u5df2\u79fb\u9664\u3002","title":"VS Code - \u6765\u81ea\u5fae\u8f6f\u7684\u9a9a\u64cd\u4f5c"},{"content":"\u641c\u4e86\u4e0d\u5c11\u5199\u6cd5\uff0c\u56e0 Markdown \u6ca1\u6709\u786e\u5207\u6807\u51c6\u548c\u5b9e\u73b0\u6240\u4ee5\u65e0\u6cd5\u7edf\u4e00\uff0c\u76ee\u524d\u627e\u5230\u4e00\u79cd\u5728 GitHub \u4eb2\u6d4b\u6709\u6548\u7684\u65b9\u6cd5\uff0c\u7b80\u5355\u8bb0\u5f55\u3002\n&lt;h1 align=&#34;center&#34;&gt; HEADING TITLE &lt;\/h1&gt; ","permalink":"https:\/\/wi1dcard.dev\/posts\/markdown-center-heading\/","summary":"\u641c\u4e86\u4e0d\u5c11\u5199\u6cd5\uff0c\u56e0 Markdown \u6ca1\u6709\u786e\u5207\u6807\u51c6\u548c\u5b9e\u73b0\u6240\u4ee5\u65e0\u6cd5\u7edf\u4e00\uff0c\u76ee\u524d\u627e\u5230\u4e00\u79cd\u5728 GitHub \u4eb2\u6d4b\u6709\u6548\u7684\u65b9\u6cd5\uff0c\u7b80\u5355\u8bb0\u5f55\u3002\n&lt;h1 align=&#34;center&#34;&gt; HEADING TITLE &lt;\/h1&gt; ","title":"Markdown \u6807\u9898\u5c45\u4e2d"},{"content":"\u76ee\u524d\u4efb\u804c\u516c\u53f8\uff0c\u6bcf\u5468\u4e00\u65e5\u5e38\u66f4\u65b0\u9700\u8981\u6253\u5305\u300c\u4e0a\u4e2a\u7248\u672c\u300d\u5230\u300c\u6700\u65b0\u4ee3\u7801\u300d\u7684\u538b\u7f29\u5305\uff0c\u56fe\u65b9\u4fbf\u5199\u6210\u547d\u4ee4\uff0c\u4ee5\u4fbf\u540e\u7eed\u4f7f\u7528\u3002\n0x00 \u601d\u8def  git diff \u67e5\u627e\u300c\u4e0a\u4e2a\u7248\u672c\u7684\u63d0\u4ea4\u300d-&gt;\u300c\u6700\u65b0\u63d0\u4ea4\u300d\u7684\u6587\u4ef6\u533a\u522b\u3002 \u5229\u7528\u5404\u7c7b\u538b\u7f29\u5de5\u5177\u6253\u5305\u538b\u7f29\u6587\u4ef6\u3002  0x01 \u4ee3\u7801 git diff --diff-filter=d --name-only &lt;COMMIT_ID&gt; HEAD | xargs tar cvf &lt;FILE_NAME&gt; --exclude=&lt;EXCLUDE&gt;  --diff-filter=d\uff1a\u5ffd\u7565\u5220\u9664\u7684\u6587\u4ef6 --name-only\uff1a\u53ea\u5bfc\u51fa\u6587\u4ef6\u540d &lt;COMMIT_ID&gt;\uff1a\u4ece\u54ea\u6b21\u63d0\u4ea4\u5f00\u59cb\u5bfc\u51fa HEAD\uff1a\u5230\u6700\u65b0\u7684\u63d0\u4ea4 &lt;FILE_NAME&gt;\uff1a\u6253\u5305\u7684\u6587\u4ef6\u8def\u5f84 &lt;EXCLUDE&gt;\uff1a\u6392\u9664\u6587\u4ef6\u6216\u76ee\u5f55  \u53e6\u5916\uff0c\u5982\u4e0d\u9700\u8981\u6253\u5305\uff0c\u53ea\u9700\u62f7\u8d1d\uff0c\u53ef\u5c06 tar \u66ff\u6362\u4e3a cp \u547d\u4ee4\uff1a\nxargs -I{} cp --parents {} &lt;DIR_NAME&gt;  &lt;DIR_NAME&gt;\uff1a\u590d\u5236\u5230\u7684\u76ee\u5f55\u540d  \u53ef\u9009\u4f7f\u7528 7z \u6253\u5305\uff08Windows \u4e0b\u9700\u8981\u5148\u914d\u7f6e 7z \u7684\u73af\u5883\u53d8\u91cf\uff09\ngit diff --diff-filter=d --name-only &lt;COMMIT_ID&gt; HEAD | xargs 7z a &lt;FILE_NAME&gt; 0x02 \u6539\u8fdb \u82e5\u6bcf\u6b21\u7248\u672c\u90fd\u6309\u89c4\u5b9a\u6253 Tag \u7684\u8bdd\uff0c\u53ef\u4ee5\u4f7f\u7528\u5982\u4e0b\u547d\u4ee4\u81ea\u52a8\u83b7\u53d6\u6700\u8fd1\u7684 Tag \u4fe1\u606f\uff0c\u7528\u4e8e\u786e\u8ba4\u6700\u65b0\u7248\u672c\u3002\ngit describe --tags `git rev-list --tags --max-count=1` ","permalink":"https:\/\/wi1dcard.dev\/posts\/pack-incremental-updates-using-git\/","summary":"\u76ee\u524d\u4efb\u804c\u516c\u53f8\uff0c\u6bcf\u5468\u4e00\u65e5\u5e38\u66f4\u65b0\u9700\u8981\u6253\u5305\u300c\u4e0a\u4e2a\u7248\u672c\u300d\u5230\u300c\u6700\u65b0\u4ee3\u7801\u300d\u7684\u538b\u7f29\u5305\uff0c\u56fe\u65b9\u4fbf\u5199\u6210\u547d\u4ee4\uff0c\u4ee5\u4fbf\u540e\u7eed\u4f7f\u7528\u3002\n0x00 \u601d\u8def  git diff \u67e5\u627e\u300c\u4e0a\u4e2a\u7248\u672c\u7684\u63d0\u4ea4\u300d-&gt;\u300c\u6700\u65b0\u63d0\u4ea4\u300d\u7684\u6587\u4ef6\u533a\u522b\u3002 \u5229\u7528\u5404\u7c7b\u538b\u7f29\u5de5\u5177\u6253\u5305\u538b\u7f29\u6587\u4ef6\u3002  0x01 \u4ee3\u7801 git diff --diff-filter=d --name-only &lt;COMMIT_ID&gt; HEAD | xargs tar cvf &lt;FILE_NAME&gt; --exclude=&lt;EXCLUDE&gt;  --diff-filter=d\uff1a\u5ffd\u7565\u5220\u9664\u7684\u6587\u4ef6 --name-only\uff1a\u53ea\u5bfc\u51fa\u6587\u4ef6\u540d &lt;COMMIT_ID&gt;\uff1a\u4ece\u54ea\u6b21\u63d0\u4ea4\u5f00\u59cb\u5bfc\u51fa HEAD\uff1a\u5230\u6700\u65b0\u7684\u63d0\u4ea4 &lt;FILE_NAME&gt;\uff1a\u6253\u5305\u7684\u6587\u4ef6\u8def\u5f84 &lt;EXCLUDE&gt;\uff1a\u6392\u9664\u6587\u4ef6\u6216\u76ee\u5f55  \u53e6\u5916\uff0c\u5982\u4e0d\u9700\u8981\u6253\u5305\uff0c\u53ea\u9700\u62f7\u8d1d\uff0c\u53ef\u5c06 tar \u66ff\u6362\u4e3a cp \u547d\u4ee4\uff1a","title":"Git \u4ed3\u5e93\u6253\u5305\u589e\u91cf\u66f4\u65b0\u5305"},{"content":"\u6b64\u65b9\u6cd5\u622a\u81f3\u672c\u6587\u53d1\u5e03\u65f6\u6700\u65b0\u7248\u672c\uff081.02.1806120\uff09\u6709\u6548\u3002\nStep 1 \u590d\u5236\u4e00\u4efd\u5fae\u4fe1\u5f00\u53d1\u8005\u5de5\u5177\u5b89\u88c5\u76ee\u5f55\u5168\u90e8\u6587\u4ef6\u3002\nStep 2 \u6253\u5f00\u65b0\u76ee\u5f55\uff0c\u627e\u5230 package.nw\/package.json \u6587\u4ef6\u3002\nStep 3 \u7f16\u8f91\u6b64\u6587\u4ef6\uff0c\u65b0\u589e\u4e00\u9879 &quot;single-instance&quot;: false\uff0c\u5e76\u4fee\u6539 name \u968f\u4fbf\u6362\u4e2a\u540d\u5b57\u5373\u53ef\u3002\n\u4f8b\u5982\uff1a\n{ &#34;single-instance&#34;: false, ... &#34;name&#34;: &#34;\u5751\u7239web\u5f00\u53d1\u8005\u5de5\u5177&#34;, ... } Step 4 \u542f\u52a8\u65b0\u76ee\u5f55\u4e0b\u7684\u5fae\u4fe1\u5f00\u53d1\u8005\u5de5\u5177\u3002\n\u53c2\u8003 https:\/\/github.com\/nwjs\/nw.js\/wiki\/Manifest-format#single-instance\n","permalink":"https:\/\/wi1dcard.dev\/posts\/wechat-dev-tool-multi-instance\/","summary":"\u6b64\u65b9\u6cd5\u622a\u81f3\u672c\u6587\u53d1\u5e03\u65f6\u6700\u65b0\u7248\u672c\uff081.02.1806120\uff09\u6709\u6548\u3002\nStep 1 \u590d\u5236\u4e00\u4efd\u5fae\u4fe1\u5f00\u53d1\u8005\u5de5\u5177\u5b89\u88c5\u76ee\u5f55\u5168\u90e8\u6587\u4ef6\u3002\nStep 2 \u6253\u5f00\u65b0\u76ee\u5f55\uff0c\u627e\u5230 package.nw\/package.json \u6587\u4ef6\u3002\nStep 3 \u7f16\u8f91\u6b64\u6587\u4ef6\uff0c\u65b0\u589e\u4e00\u9879 &quot;single-instance&quot;: false\uff0c\u5e76\u4fee\u6539 name \u968f\u4fbf\u6362\u4e2a\u540d\u5b57\u5373\u53ef\u3002\n\u4f8b\u5982\uff1a\n{ &#34;single-instance&#34;: false, .","title":"\u5fae\u4fe1\u5f00\u53d1\u8005\u5de5\u5177 - \u591a\u7528\u6237\u591a\u5f00\u5b9e\u8df5"},{"content":"\u6700\u8fd1\u7a81\u7136\u5bf9\u4ee3\u7801\u8d28\u91cf\u68c0\u67e5\u611f\u5174\u8da3\uff0c\u51b3\u5b9a\u5bf9\u516c\u53f8\u9879\u76ee\u7684\u4ee3\u7801\u5197\u4f59\u8fdb\u884c\u5f7b\u67e5\u3002\u7ecf\u8fc7\u641c\u7d22\u53d1\u73b0\u4e00\u6b3e\u4e0d\u9519\u7684\u5de5\u5177\uff0c\u9488\u5bf9\u590d\u5236\u7c98\u8d34\u7684\u4ee3\u7801\u6709\u4e0d\u9519\u7684\u8bc6\u522b\u7387\uff0c\u5728\u6b64\u63a8\u8350\u3002\n0x00 \u51c6\u5907 \u9879\u76ee\u5730\u5740\uff1ahttps:\/\/github.com\/sebastianbergmann\/phpcpd\n0x01 \u5b89\u88c5  \u76f4\u63a5\u4e0b\u8f7d\u4ee3\u7801\u5305  wget https:\/\/phar.phpunit.de\/phpcpd.phar chmod +x phpcpd.phar \u6216\u4f7f\u7528 Composer \u5168\u5c40\u5b89\u88c5  composer global require sebastian\/phpcpd 0x02 \u4f7f\u7528 \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u8981\u5e26\u4e0a\u4ee3\u7801\u6587\u4ef6\u5939\u8def\u5f84\u5373\u53ef\u3002\nphp phpcpd.phar &lt;PATH_TO_YOUR_SRC&gt; \u5b9e\u9645\u4f7f\u7528\u65f6\u9047\u5230\u4e00\u4e2a\u5c0f\u95ee\u9898\uff0c\u5728\u5206\u6790\u5927\u6982 20w \u884c\u4ee3\u7801\u65f6\uff0c\u62a5\u9519\u63d0\u793a\u5185\u5b58\u5360\u7528\u8d85\u51fa\u9650\u5236\uff0c\u89e3\u51b3\u65b9\u6848\uff1a\nphp -d memory_limit=1024M phpcpd.phar &lt;PATH_TO_YOUR_SRC&gt; \u5982\u4e0a\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-copy-paste-detector\/","summary":"\u6700\u8fd1\u7a81\u7136\u5bf9\u4ee3\u7801\u8d28\u91cf\u68c0\u67e5\u611f\u5174\u8da3\uff0c\u51b3\u5b9a\u5bf9\u516c\u53f8\u9879\u76ee\u7684\u4ee3\u7801\u5197\u4f59\u8fdb\u884c\u5f7b\u67e5\u3002\u7ecf\u8fc7\u641c\u7d22\u53d1\u73b0\u4e00\u6b3e\u4e0d\u9519\u7684\u5de5\u5177\uff0c\u9488\u5bf9\u590d\u5236\u7c98\u8d34\u7684\u4ee3\u7801\u6709\u4e0d\u9519\u7684\u8bc6\u522b\u7387\uff0c\u5728\u6b64\u63a8\u8350\u3002\n0x00 \u51c6\u5907 \u9879\u76ee\u5730\u5740\uff1ahttps:\/\/github.com\/sebastianbergmann\/phpcpd\n0x01 \u5b89\u88c5  \u76f4\u63a5\u4e0b\u8f7d\u4ee3\u7801\u5305  wget https:\/\/phar.phpunit.de\/phpcpd.phar chmod +x phpcpd.phar \u6216\u4f7f\u7528 Composer \u5168\u5c40\u5b89\u88c5  composer global require sebastian\/phpcpd 0x02 \u4f7f\u7528 \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u8981\u5e26\u4e0a\u4ee3\u7801\u6587\u4ef6\u5939\u8def\u5f84\u5373\u53ef\u3002","title":"PHPCPD - \u68c0\u67e5\u590d\u5236\u7c98\u8d34\u7684 PHP \u4ee3\u7801"},{"content":"\u5728\u4f7f\u7528 macOS \u901a\u8fc7 SSH \u8fde\u63a5\u5230\u6811\u8393\u6d3e\u65f6\uff0c\u9047\u5230 Connection to *** closed by remote host. \u7684\u95ee\u9898\uff0c\u4e0b\u9762\u4ecb\u7ecd\u4e24\u79cd\u89e3\u51b3\u65b9\u6848\u3002\n\u6307\u5b9a KeepAlive \u53c2\u6570 ssh -o TCPKeepAlive=yes {HOST} \u4fee\u6539 SSH \u5ba2\u6237\u7aef\u914d\u7f6e \u4fee\u6539\u6216\u521b\u5efa ~\/.ssh\/config \u6587\u4ef6\uff1a\nKeepAlive yes ServerAliveInterval 30 ","permalink":"https:\/\/wi1dcard.dev\/posts\/ssh-connection-closed-by-remote-host\/","summary":"\u5728\u4f7f\u7528 macOS \u901a\u8fc7 SSH \u8fde\u63a5\u5230\u6811\u8393\u6d3e\u65f6\uff0c\u9047\u5230 Connection to *** closed by remote host. \u7684\u95ee\u9898\uff0c\u4e0b\u9762\u4ecb\u7ecd\u4e24\u79cd\u89e3\u51b3\u65b9\u6848\u3002\n\u6307\u5b9a KeepAlive \u53c2\u6570 ssh -o TCPKeepAlive=yes {HOST} \u4fee\u6539 SSH \u5ba2\u6237\u7aef\u914d\u7f6e \u4fee\u6539\u6216\u521b\u5efa ~\/.","title":"SSH \u975e\u6d3b\u52a8\u8fde\u63a5\u88ab\u5173\u95ed"},{"content":" \u7fa4\u6656\u592a\u8d35\uff01\u82e5\u662f\u4e0d\u4ecb\u610f USB 2.0 \u548c 100 Mbps \u5e26\u5bbd\u7684\u8bdd\uff0c\u7528\u6811\u8393\u6d3e + \u79fb\u52a8\u786c\u76d8\u505a\u4e2a\u4f4e\u529f\u8017\u5c0f\u578b NAS \u4e5f\u662f\u4e0d\u9519\u7684\u9009\u62e9\uff1b\u642d\u5efa Samba \u7684\u6559\u7a0b\u5230\u5904\u90fd\u662f\uff0c\u672c\u7bc7\u5c06\u4ecb\u7ecd\u4ee5\u6b63\u786e\u7684\u59ff\u52bf\u642d\u5efa AFP \u5171\u4eab + Time Machine\u3002\n  The following step are the ones that enable Time Machine backups with Raspberry Pi plus a bit of polishing to my taste.\n0x00 Prepare Format the hard drive I had a hard-drive serving as Time Machine disk. However, I couldn&rsquo;t mount the disk due to Apple Core Storage:\nDisk \/dev\/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical\/physical): 512 bytes \/ 512 bytes I\/O size (minimum\/optimal): 512 bytes \/ 512 bytes Disklabel type: gpt Disk identifier: DE07BD84-C4E1-4229-81CD-E146E04D46C6 Device Start End Sectors Size Type \/dev\/sda1 40 409639 409600 200M EFI System \/dev\/sda2 409640 975539735 975130096 465G Apple Core storage \/dev\/sda3 975539736 975801879 262144 128M Apple boot \/dev\/sda4 975802368 1953523711 977721344 466.2G Microsoft basic data Since the backups on that disk were a bit outdated I decided to format the partition and give it a go. Another alternative would be to use Disk Utility to get rid of Apple Core Storage but in my case not worth the effort.\nSo, format the HD on your Mac using Disk Utility. Settings used:\n Name: Time Machine Format: Mac OS Extended (Journaled) Scheme: GUID Partition Map  Ensure Pi has permissions to control the drive Go to the Finder, then right-click the drive in the sidebar. Click Get Info.\nClick the lock at bottom right, then enter your password. Next, check Ignore ownership on this volume. and give Read &amp; Write permissions to everyone. And do not forget to click Apply to enclosed items.\nLinux cannot write data into journaled hfs+ file system, so you also need to disable that:\ndiskutil list Find your drive and partition identifier (like: disk2s2), then run:\ndiskutil disableJournal \/dev\/disk2s2 ... Journaling has been disabled for volume *** on disk2s2 Install tools for Apple-formatted drives Go to Pi (ssh&rsquo;ed it!) and run:\nsudo apt-get update sudo apt-get upgrade sudo apt-get --assume-yes install hfsprogs hfsplus Mount the drive   Find the drive:\nsudo fdisk -l ... Disk \/dev\/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical\/physical): 512 bytes \/ 512 bytes I\/O size (minimum\/optimal): 512 bytes \/ 512 bytes Disklabel type: gpt Disk identifier: DE07BD84-C4E1-4229-81CD-E146E04D46C6 Device Start End Sectors Size Type \/dev\/sda1 40 409639 409600 200M EFI System \/dev\/sda2 409640 975539735 975130096 465G Apple HFS\/HFS+ \/dev\/sda3 975802368 1953523711 977721344 466.2G Microsoft basic data In my case my HD is connected to USB and the device is \/dev\/sda2. A good hint is the fs type Apple HFS\/HFS+ or on other tools hfsx.\n  Create your mounting point:\nsudo mkdir -p \/media\/time_machine   Check if Pi already auto-mounted your drive:\nsudo mount If it&rsquo;s mounted, you need to un-mount it or give it write permissions. In my case I didn&rsquo;t want to have it mounted on \/media\/pi\/Time Machine so I un-mounted it:\nsudo umount \/dev\/sda2   Mount drive using your editor of choice:\nsudo nano \/etc\/fstab Add to the end of the file:\n\/dev\/sda2 \/media\/time_machine hfsplus force,rw,user,noauto,x-systemd.automount 0 0 Mount the drive:\nsudo mount -a Check if it&rsquo;s mounted by finding the line like the bellow:\nsudo mount ... \/dev\/sda2 on \/media\/time_machine type hfsplus (rw,nosuid,nodev,noexec,relatime,umask=22,uid=0,gid=0,nls=utf8,user)   0x01 Netatalk Netatalk simulates AFP, the network protocol Apple currently users for Time Machine backups.\nInstall Install required packages:\nsudo apt-get install build-essential libevent-dev libssl-dev libgcrypt-dev libkrb5-dev libpam0g-dev libwrap0-dev libdb-dev libtdb-dev default-libmysqlclient-dev avahi-daemon libavahi-client-dev libacl1-dev libldap2-dev libcrack2-dev systemtap-sdt-dev libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev libio-socket-inet6-perl tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-dev Get the tarball from Netatalk Web Site, download and extract it.\ntar xvf netatalk-3.1.11.tar.bz2 cd netatalk-3.1.11 Do configure, then make and install.\n.\/configure \\ --with-init-style=debian-systemd \\ --without-libevent \\ --without-tdb \\ --with-cracklib \\ --enable-krbV-uam \\ --with-pam-confdir=\/etc\/pam.d \\ --with-dbus-daemon=\/usr\/bin\/dbus-daemon \\ --with-dbus-sysconf-dir=\/etc\/dbus-1\/system.d \\ --with-tracker-pkgconfig-version=1.0 sudo make sudo make install Alternatively, you can check features and paths using &ldquo;netatalk -V&rdquo; and &ldquo;afpd -V&rdquo;.\nConfigure Edit afp.conf.\nsudo nano \/usr\/local\/etc\/afp.conf Add to the end:\n[Global] mimic model = TimeCapsule6,106 [RPi-TimeMachine] path = \/media\/time_machine time machine = yes 0x02 Launch Services sudo service avahi-daemon start sudo service netatalk start sudo systemctl enable avahi-daemon sudo systemctl enable netatalk 0x03 Finish Give your Pi a static IP Go to your router and assign a static IP to your Pi.\nConnect to Time Machine Go to your Mac Finder you should see your Raspberry Pi there. Click on Connect as and insert your credentials (user: timemachine). If doesn&rsquo;t work, connect to your Pi through its static IP. Open Finder, then hit Command+K on your keyboard and insert:\nafp:\/\/{YOUR_PI_IP} Configure your Mac Time Machine Go to System Preferences &gt; Time Machine and clik on Select Disk.... Your Pi should show on the list. Select and use the settings that work best.\n0x04 References  https:\/\/github.com\/mr-bt\/raspberrypi-timemachine http:\/\/netatalk.sourceforge.net\/wiki\/index.php\/Install_Netatalk_3.1.11_on_Ubuntu_16.04_Xenial https:\/\/wiki.archlinux.org\/index.php\/Netatalk https:\/\/support.apple.com\/zh-cn\/HT202944 https:\/\/wiki.archlinux.org\/index.php\/Fstab  ","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-time-machine\/","summary":"\u7fa4\u6656\u592a\u8d35\uff01\u82e5\u662f\u4e0d\u4ecb\u610f USB 2.0 \u548c 100 Mbps \u5e26\u5bbd\u7684\u8bdd\uff0c\u7528\u6811\u8393\u6d3e + \u79fb\u52a8\u786c\u76d8\u505a\u4e2a\u4f4e\u529f\u8017\u5c0f\u578b NAS \u4e5f\u662f\u4e0d\u9519\u7684\u9009\u62e9\uff1b\u642d\u5efa Samba \u7684\u6559\u7a0b\u5230\u5904\u90fd\u662f\uff0c\u672c\u7bc7\u5c06\u4ecb\u7ecd\u4ee5\u6b63\u786e\u7684\u59ff\u52bf\u642d\u5efa AFP \u5171\u4eab + Time Machine\u3002\n  The following step are the ones that enable Time Machine backups with Raspberry Pi plus a bit of polishing to my taste.","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0 - Time Machine"},{"content":"\u8bf4\u5230\u5b57\u7b26\u4e32\u8f6c\u6574\u578b\uff0cPHP \u91cc\u5e38\u7528\u7684\u4e24\u4e2a\u65b9\u6cd5\u76f8\u4fe1\u5404\u4f4d\u90fd\u6709\u4e86\u89e3\uff0c\u4f46\u5176\u4e2d\u5fae\u5c0f\u7684\u533a\u522b\u7f3a\u9c9c\u4e3a\u4eba\u77e5\u3002\u672c\u6587\u7b80\u5355\u68b3\u7406\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u9605\u3002\n\u529f\u80fd \u5bf9\u4e8e\u5341\u8fdb\u5236\u7684\u8f6c\u6362\uff0c\u4e24\u79cd\u65b9\u5f0f\u7684\u529f\u80fd\u662f\u5b8c\u5168\u4e00\u81f4\u7684\uff1a\n$int = intval($str); \/\/ \u7b49\u4ef7\u4e8e $int = (int) $str; \u800c intval() \u5177\u5907\u4e00\u4e2a\u53ef\u9009\u53c2\u6570 $base \u9ed8\u8ba4\u503c\u4e3a 10\uff0c\u7528\u4e8e\u8f6c\u6362\u4e0d\u540c\u6765\u81ea\u8fdb\u5236\u7684\u6570\u636e\uff1a\n$int = intval(&#39;0123&#39;, 8); \/\/ == 83 \u7531\u8fd9\u4e2a\u53c2\u6570\uff0c\u53c8\u5f15\u8d77\u53e6\u4e00\u6761\u9700\u8981\u6ce8\u610f\u7684\u70b9\uff0c\u5148\u770b\u4f8b\u5b50\uff1a\n$test_int = 12; $test_float = 12.8; $test_string = &#34;12&#34;; echo (int) $test_int; \/\/ == 12 echo (int) $test_float; \/\/ == 12 echo (int) $test_string; \/\/ == 12  echo intval($test_int, 8); \/\/ == 12 echo intval($test_float, 8) \/\/ == 12 echo intval($test_string, 8); \/\/ == 10 intval() \u4f1a\u5c06\u7c7b\u578b\u5df2\u7ecf\u662f int \u6216 float \u7684\u6570\u636e\u5f53\u4f5c\u300c\u65e0\u9700\u8f6c\u6362\u300d\u800c\u76f4\u63a5\u8fd4\u56de\uff01\n\u6240\u4ee5\u5982\u4e0a\uff0c$test_int \u548c $test_float \u5e76\u6ca1\u6709\u6309\u7167\u516b\u8fdb\u5236\u8f6c\u6362\uff0c\u4f7f\u7528\u65f6\u4e00\u5b9a\u9700\u8981\u6ce8\u610f\u907f\u514d\u8e29\u5751\u3002\n\u6027\u80fd (int) \u4e0e intval() \u6027\u80fd\u51e0\u4e4e\u65e0\u5f02\u3002\u4ee5\u4e0b\u6458\u81ea\u672c\u6587\u8bc4\u8bba\uff08\u611f\u8c22 @CismonX\uff09\uff1a\n If you call intval() with only one argument, it will be compiled to ZEND_CAST instruction by function zend_try_compile_special_func(), yielding identical opcode to that of (int). Thus, there&rsquo;s no performance issue with intval() here.\n  The same is true for many other internal functions, like strval(), call_user_func(), etc., where function calls are optimized into opcode instructions at compile time. You can try that yourself using phpdbg.\n \u53c2\u8003 PHP \u5b98\u65b9\u624b\u518c\uff1a\n PHP: \u7c7b\u578b\u8f6c\u6362\u7684\u5224\u522b - Manual PHP: intval - Manual  \u5176\u5b83\uff1a\n https:\/\/stackoverflow.com\/questions\/1912599\/is-there-any-particular-difference-between-intval-and-casting-to-int-int-x https:\/\/hakre.wordpress.com\/2010\/05\/13\/php-casting-vs-intval\/  ","permalink":"https:\/\/wi1dcard.dev\/posts\/php-intval-vs-int-casting\/","summary":"\u8bf4\u5230\u5b57\u7b26\u4e32\u8f6c\u6574\u578b\uff0cPHP \u91cc\u5e38\u7528\u7684\u4e24\u4e2a\u65b9\u6cd5\u76f8\u4fe1\u5404\u4f4d\u90fd\u6709\u4e86\u89e3\uff0c\u4f46\u5176\u4e2d\u5fae\u5c0f\u7684\u533a\u522b\u7f3a\u9c9c\u4e3a\u4eba\u77e5\u3002\u672c\u6587\u7b80\u5355\u68b3\u7406\uff0c\u4ee5\u5907\u65e5\u540e\u67e5\u9605\u3002\n\u529f\u80fd \u5bf9\u4e8e\u5341\u8fdb\u5236\u7684\u8f6c\u6362\uff0c\u4e24\u79cd\u65b9\u5f0f\u7684\u529f\u80fd\u662f\u5b8c\u5168\u4e00\u81f4\u7684\uff1a\n$int = intval($str); \/\/ \u7b49\u4ef7\u4e8e $int = (int) $str; \u800c intval() \u5177\u5907\u4e00\u4e2a\u53ef\u9009\u53c2\u6570 $base \u9ed8\u8ba4\u503c\u4e3a 10\uff0c\u7528\u4e8e\u8f6c\u6362\u4e0d\u540c\u6765\u81ea\u8fdb\u5236\u7684\u6570\u636e\uff1a\n$int = intval(&#39;0123&#39;, 8); \/\/ == 83 \u7531\u8fd9\u4e2a\u53c2\u6570\uff0c\u53c8\u5f15\u8d77\u53e6\u4e00\u6761\u9700\u8981\u6ce8\u610f\u7684\u70b9\uff0c\u5148\u770b\u4f8b\u5b50\uff1a","title":"PHP intval() \u4e0e (int) \u8f6c\u6362\u7684\u533a\u522b"},{"content":"\u8fdb\u5236\u8f6c\u6362\uff1a\nbin = Convert.ToString(dec, 2); \u7f3a\u4f4d\u8865\u96f6\uff1a\nbin = bin.PadLeft(8, &#39;0&#39;); ","permalink":"https:\/\/wi1dcard.dev\/posts\/csharp-dec-to-zero-padded-bin\/","summary":"\u8fdb\u5236\u8f6c\u6362\uff1a\nbin = Convert.ToString(dec, 2); \u7f3a\u4f4d\u8865\u96f6\uff1a\nbin = bin.PadLeft(8, &#39;0&#39;); ","title":"C# \u4e8c\u8fdb\u5236\u8f6c\u6362 \u7f3a\u4f4d\u8865\u96f6"},{"content":"\u524d\u51e0\u5929\u624b\u8d31\u5565\u4e5f\u6ca1\u770b\u6267\u884c brew upgrade\uff0c\u968f\u540e\u5c31\u540e\u6094\u4e86&hellip; \u51e1\u4e8b\u6ca1\u6709\u4e00\u5e06\u98ce\u987a\uff0c\u5728\u6b64\u603b\u7ed3\u5347\u7ea7\u7ecf\u9a8c\uff0c\u4ee5\u4f9b\u540e\u4eba\u53c2\u8003\u3002\n0x00 \u573a\u666f\uff1a\u6267\u884c mysql.server start \u63d0\u793a The server quit without updating PID file mysql.server start\u3002\n\u89e3\u51b3\uff1a\n cd \/usr\/local\/var\/mysql\/\uff0c\u5207\u6362\u5230 MySQL \u6570\u636e\u76ee\u5f55\uff08macOS \u4f7f\u7528 brew \u5b89\u88c5\u7684 MySQL \u9ed8\u8ba4\u6570\u636e\u5b58\u50a8\u8def\u5f84\u5982\u4e0a\uff09\u3002 rm *.err *.pid\uff0c\u5220\u9664\u539f PID \u548c ERR \u6587\u4ef6\u3002 rm ib_logfile*\uff0c\u5220\u9664\u539f logfile\u3002  \u518d\u6b21\u5c1d\u8bd5\uff0c\u5982\u4ecd\u65e7\u62a5\u9519\uff0c\u53ef\u5c1d\u8bd5\uff1a\n cd \/usr\/local\/Cellar\/mysql\/{5.*}\/bin\uff0c\u5207\u6362\u5230\u65e7\u7248\u672c MySQL \u76ee\u5f55\uff08macOS \u4f7f\u7528 brew \u5b89\u88c5\u7684 MySQL \u9ed8\u8ba4\u8def\u5f84\u5982\u4e0a\uff09\u3002 .\/mysql.server start &amp;&amp; .\/mysql.server stop\uff0c\u5c1d\u8bd5\u542f\u52a8\u5e76\u6b63\u5e38\u7ed3\u675f\u3002  \u518d\u6b21\u542f\u52a8\u65b0\u7248\u672c\u670d\u52a1\u5668\uff0c\u5373\u6b63\u5e38\u3002\n0x01 \u573a\u666f\uff1amysql -uroot \u8fdb\u5165\u6570\u636e\u5e93\u540e\uff0cshow databases; \u63d0\u793a ERROR 1449 (HY000): The user specified as a definer ('mysql.infoschema'@'localhost') does not exist\u3002\n\u89e3\u51b3\uff1a\u6267\u884c mysql_upgrade -u root -p \u5373\u53ef\u3002\n0x02 \u573a\u666f\uff1a\u8bbe\u7f6e sql_mode \u63d0\u793a SQLSTATE[42000]: Syntax error or access violation: 1231 Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'\u3002\n\u89e3\u51b3\uff1aMySQL 8.0 \u5df2\u5e9f\u9664\u6a21\u5f0f\uff0c\u79fb\u9664 NO_AUTO_CREATE_USER \u5373\u53ef\u3002\n0xFF \u66f4\u591a&hellip;  https:\/\/www.shiqidu.com\/d\/358 https:\/\/learnku.com\/articles\/10736\/some-craters-in-mysql-8011 https:\/\/kn007.net\/topics\/the-road-to-mysql-8-0-11-update\/  ","permalink":"https:\/\/wi1dcard.dev\/posts\/upgrade-mysql-5.7-to-8.0\/","summary":"\u524d\u51e0\u5929\u624b\u8d31\u5565\u4e5f\u6ca1\u770b\u6267\u884c brew upgrade\uff0c\u968f\u540e\u5c31\u540e\u6094\u4e86&hellip; \u51e1\u4e8b\u6ca1\u6709\u4e00\u5e06\u98ce\u987a\uff0c\u5728\u6b64\u603b\u7ed3\u5347\u7ea7\u7ecf\u9a8c\uff0c\u4ee5\u4f9b\u540e\u4eba\u53c2\u8003\u3002\n0x00 \u573a\u666f\uff1a\u6267\u884c mysql.server start \u63d0\u793a The server quit without updating PID file mysql.server start\u3002\n\u89e3\u51b3\uff1a\n cd \/usr\/local\/var\/mysql\/\uff0c\u5207\u6362\u5230 MySQL \u6570\u636e\u76ee\u5f55\uff08macOS \u4f7f\u7528 brew \u5b89\u88c5\u7684 MySQL \u9ed8\u8ba4\u6570\u636e\u5b58\u50a8\u8def\u5f84\u5982\u4e0a\uff09\u3002 rm *.","title":"\u5347\u7ea7 MySQL 5.7 \u5230 8.0 \u9047\u5230\u7684\u5751"},{"content":"\u771f\u662f\u5929\u4e0b\u6ca1\u6709\u4e0d\u5751\u7684\u9762\u677f&hellip; \u76f8\u7ee7\u5b9d\u5854\u548c WDCP \u4e4b\u540e\uff0cAMH \u4e5f\u51fa\u4e86\u95ee\u9898\u3002\n0x00 \u8868\u8c61 \u62a5\u9519\u5982\u4e0b\uff1a\nPHP Warning: Module 'mysql' already loaded in Unknown on line 0\nlogs\/amh-php-errors.log \u6587\u4ef6\u5185\u4e5f\u6709\u5076\u5c14\u51fa\u73b0\u7684\u8bb0\u5f55\u3002\n0x01 \u95ee\u9898 \u7ecf\u8fc7 StackOverflow \u4e00\u756a\u67e5\u627e\uff0c\u5b9a\u4f4d\u95ee\u9898\u539f\u56e0\u5728\u4e8e\u91cd\u590d\u52a0\u8f7d MySQL \u6269\u5c55\uff0c\u6545\u67e5\u627e\u73af\u5883\u914d\u7f6e\u6587\u4ef6\u8fdb\u884c\u5220\u9664\u3002\n\u6253\u5f00\u5bf9\u5e94\u73af\u5883\u7684 php.ini \u914d\u7f6e\u6587\u4ef6\uff08\u901a\u5e38\u4f4d\u4e8e \/home\/wwwroot\/{env}\/etc\/amh-php.ini\uff09\uff0c\u4f7f\u7528 # \u6216 ; \u6ce8\u91ca extension=mysql.so \u6b64\u884c\u5373\u53ef\u3002\n0x02 \u540e\u8bb0 \u5929\u4e0b\u6ca1\u6709\u4e0d\u5751\u7684\u9762\u677f&hellip;\n\u4e5f\u6ca1\u6709\u4e0d\u5751\u7684\u4e91\u670d\u52a1&hellip;\n\u6700\u8fd1\u5904\u7406\u5404\u79cd\u5ba2\u6237\u7684\u5404\u79cd\u4e91\u670d\u52a1\u7684\u5404\u79cd\u7cfb\u7edf\u5404\u79cd\u9762\u677f\u771f\u662f\u8e29\u4e00\u5927\u5806\u5751\uff0c\u7b97\u662f\u79ef\u7d2f\u4e86\u5b9d\u8d35\u7684\u6a2a\u5411\u5bf9\u6bd4\u3001\u95ee\u9898\u5904\u7406\u7ecf\u9a8c\u3002\n\u5404\u5bb6\u5b58\u5728\u7740\u4e0d\u540c\u7684\u4f18\u52a3\u52bf\uff0c\u963f\u91cc\u5de5\u5355\u56de\u590d\u6162\u3001\u817e\u8baf\u5bf9\u8c61\u5b58\u50a8\/CDN \u70c2\u3001\u534e\u4e3a IO \u6027\u80fd\u5dee\u2026\u2026\n\u56de\u5934\u81ea\u5df1\u5c1d\u8bd5\u8f6c\u5fae\u8f6f\u5427\uff0c\u8131\u5751 Windows \u518d\u6b21\u5165\u5751 Azure\u3002\n\u53c2\u8003\uff1ahttps:\/\/stackoverflow.com\/questions\/32764981\/php-warning-module-already-loaded-in-unknown-on-line-0\n","permalink":"https:\/\/wi1dcard.dev\/posts\/amh-loaded-mysql-module-twice\/","summary":"\u771f\u662f\u5929\u4e0b\u6ca1\u6709\u4e0d\u5751\u7684\u9762\u677f&hellip; \u76f8\u7ee7\u5b9d\u5854\u548c WDCP \u4e4b\u540e\uff0cAMH \u4e5f\u51fa\u4e86\u95ee\u9898\u3002\n0x00 \u8868\u8c61 \u62a5\u9519\u5982\u4e0b\uff1a\nPHP Warning: Module 'mysql' already loaded in Unknown on line 0\nlogs\/amh-php-errors.log \u6587\u4ef6\u5185\u4e5f\u6709\u5076\u5c14\u51fa\u73b0\u7684\u8bb0\u5f55\u3002","title":"AMH \u9762\u677f\u91cd\u590d\u52a0\u8f7d MySQL \u6269\u5c55"},{"content":"\u6628\u5929\u53d1\u6587\u622a\u56fe\uff0cGitHub \u662f\u9ed1\u8272\uff08Dark\uff09\u4e3b\u9898\uff0c\u672c\u6587\u5c06\u4ecb\u7ecd\uff1a\u5982\u4f55\u5feb\u901f\u7ed9\u7f51\u7ad9\u52a0\u7279\u6280\uff08duang\uff0cduang\uff0cduang\uff09\u3002\n0x00 Stylish \u5b9e\u9645\u4e0a\uff0c\u6211\u7528\u4e86\u4e2a\u540d\u53eb\u300cStylish\u300d\u7684\u795e\u5668\uff0c\u8fd9\u73a9\u610f\u5728 Chrome \u5e94\u7528\u5546\u5e97\u53ef\u4ee5\u76f4\u63a5\u4e0b\u8f7d\uff1a\nhttps:\/\/chrome.google.com\/webstore\/detail\/fjnbnpbmkenffdnngjfgmeleoegfcffe\n\u5b89\u88c5\u540e\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee\u5b98\u65b9\u4e3b\u9898\u5546\u5e97\uff1a\nhttps:\/\/userstyles.org\/\n0x01 \u4e3b\u9898 \u63a8\u8350\u51e0\u4e2a\u6211\u5e38\u7528\u7684\u4e3b\u9898\uff1a\n GitHub Dark Google - Clean Dark Fade&#43; for Youtube Baidu Lite \u767e\u5ea6\u8f7b \u767e\u5ea6\u767e\u79d1-\u5c4f\u853d\u548c\u4f18\u5316  0x02 \u8865\u5145 Baidu Lite \u767e\u5ea6\u8f7b\uff0c\u8fd9\u4e2a\u4e3b\u9898\u6709\u4e9b\u517c\u5bb9\u6027\u95ee\u9898\uff0c\u4f8b\u5982 Logo \u91cd\u53e0\u7b49\u7b49\u3002\u539f\u4f5c\u8005\u5df2\u7ecf\u5f88\u4e45\u4e0d\u7ef4\u62a4\uff0c\u6211\u7b80\u5355\u4fee\u590d\u5e76\u6574\u4f53\u6539\u4e3a Dark \u8272\u8c03\uff0c\u653e\u51fa\u7ed9\u5927\u5bb6\u53c2\u8003\uff1ahttps:\/\/gist.github.com\/wi1dcard\/e9e1abe55fa509a588c591ecb55cd8bb","permalink":"https:\/\/wi1dcard.dev\/posts\/custom-themes-for-any-website\/","summary":"\u6628\u5929\u53d1\u6587\u622a\u56fe\uff0cGitHub \u662f\u9ed1\u8272\uff08Dark\uff09\u4e3b\u9898\uff0c\u672c\u6587\u5c06\u4ecb\u7ecd\uff1a\u5982\u4f55\u5feb\u901f\u7ed9\u7f51\u7ad9\u52a0\u7279\u6280\uff08duang\uff0cduang\uff0cduang\uff09\u3002\n0x00 Stylish \u5b9e\u9645\u4e0a\uff0c\u6211\u7528\u4e86\u4e2a\u540d\u53eb\u300cStylish\u300d\u7684\u795e\u5668\uff0c\u8fd9\u73a9\u610f\u5728 Chrome \u5e94\u7528\u5546\u5e97\u53ef\u4ee5\u76f4\u63a5\u4e0b\u8f7d\uff1a\nhttps:\/\/chrome.google.com\/webstore\/detail\/fjnbnpbmkenffdnngjfgmeleoegfcffe\n\u5b89\u88c5\u540e\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee\u5b98\u65b9\u4e3b\u9898\u5546\u5e97\uff1a\nhttps:\/\/userstyles.org\/\n0x01 \u4e3b\u9898 \u63a8\u8350\u51e0\u4e2a\u6211\u5e38\u7528\u7684\u4e3b\u9898\uff1a\n GitHub Dark Google - Clean Dark Fade&#43; for Youtube Baidu Lite \u767e\u5ea6\u8f7b \u767e\u5ea6\u767e\u79d1-\u5c4f\u853d\u548c\u4f18\u5316  0x02 \u8865\u5145 Baidu Lite \u767e\u5ea6\u8f7b\uff0c\u8fd9\u4e2a\u4e3b\u9898\u6709\u4e9b\u517c\u5bb9\u6027\u95ee\u9898\uff0c\u4f8b\u5982 Logo \u91cd\u53e0\u7b49\u7b49\u3002\u539f\u4f5c\u8005\u5df2\u7ecf\u5f88\u4e45\u4e0d\u7ef4\u62a4\uff0c\u6211\u7b80\u5355\u4fee\u590d\u5e76\u6574\u4f53\u6539\u4e3a Dark \u8272\u8c03\uff0c\u653e\u51fa\u7ed9\u5927\u5bb6\u53c2\u8003\uff1ahttps:\/\/gist.","title":"Stylish - \u81ea\u5b9a\u4e49 GitHub \/ Google \/ Youtube \u4e3b\u9898"},{"content":"\u4e0d\u591a\u8bf4\u4e86\uff0c\u4e0a\u56fe\uff0c\u81ea\u5df1\u611f\u53d7\u5427\u3002\nhttps:\/\/github.com\/tencentyun\/cos-php-sdk-v5\/pull\/72\n","permalink":"https:\/\/wi1dcard.dev\/posts\/qcloud-terrible-cos\/","summary":"\u4e0d\u591a\u8bf4\u4e86\uff0c\u4e0a\u56fe\uff0c\u81ea\u5df1\u611f\u53d7\u5427\u3002\nhttps:\/\/github.com\/tencentyun\/cos-php-sdk-v5\/pull\/72","title":"\u817e\u8baf\u4e91\u5c4e\u4e00\u6837\u7684\u5bf9\u8c61\u5b58\u50a8"},{"content":"\u8fd1\u671f\u5728\u4f7f\u7528\u5b9d\u5854\u9762\u677f\u90e8\u7f72 PHP \u9879\u76ee\u65f6\uff0c\u4e0a\u4f20\u6587\u4ef6\u7684\u573a\u666f\uff0cPHP \u65e0\u6cd5\u5bf9\u4e34\u65f6\u6587\u4ef6\u8fdb\u884c\u6253\u5f00\u64cd\u4f5c\uff0c\u65e0\u6cd5\u8ba1\u7b97sha1\u3001md5\uff0c\u9042\u8fdb\u884c\u6392\u67e5\u3002\n0x00 \u62a5\u9519 sha1_file(): open_basedir restriction in effect. File(\/www\/wwwroot\/tmp\/***) is not within the allowed path(s): (***)\n0x01 \u539f\u56e0 \u65b0\u7248\u5b9d\u5854\u9762\u677f\u521b\u5efa\u7ad9\u70b9\u65f6\u9ed8\u8ba4\u6dfb\u52a0 .user.ini\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a\nopen_basedir=\/www\/wwwroot\/test.test\/:\/tmp\/:\/proc\/ \u5173\u4e8e open_basedir \u73af\u5883\u53d8\u91cf\uff0c\u53c2\u89c1\uff1ahttps:\/\/blog.csdn.net\/fdipzone\/article\/details\/54562656\u3002\n0x02 \u89e3\u51b3 \u65b9\u6848\u6709\u4e8c\uff1a\n \u5220\u9664 .user.ini \u6587\u4ef6\u3002 \u5728 open_basedir=*** \u540e\u8ffd\u52a0 : + \u62a5\u9519\u4fe1\u606f\u5185\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 \/www\/wwwroot\/tmp\/***\u3002  ","permalink":"https:\/\/wi1dcard.dev\/posts\/baota-open-basedir-restriction\/","summary":"\u8fd1\u671f\u5728\u4f7f\u7528\u5b9d\u5854\u9762\u677f\u90e8\u7f72 PHP \u9879\u76ee\u65f6\uff0c\u4e0a\u4f20\u6587\u4ef6\u7684\u573a\u666f\uff0cPHP \u65e0\u6cd5\u5bf9\u4e34\u65f6\u6587\u4ef6\u8fdb\u884c\u6253\u5f00\u64cd\u4f5c\uff0c\u65e0\u6cd5\u8ba1\u7b97sha1\u3001md5\uff0c\u9042\u8fdb\u884c\u6392\u67e5\u3002\n0x00 \u62a5\u9519 sha1_file(): open_basedir restriction in effect. File(\/www\/wwwroot\/tmp\/***) is not within the allowed path(s): (***)\n0x01 \u539f\u56e0 \u65b0\u7248\u5b9d\u5854\u9762\u677f\u521b\u5efa\u7ad9\u70b9\u65f6\u9ed8\u8ba4\u6dfb\u52a0 .","title":"\u5b9d\u5854\u9762\u677f PHP \u6253\u5f00\u6587\u4ef6\u5931\u8d25\u539f\u56e0\u6392\u67e5"},{"content":"\u8981\u8d70\u521b\u610f\u8def\u7ebf\u597d\u5417\uff01print \u6211\u7231\u4f60 \u4e4b\u6d41\u6015\u4e0d\u662f\u5728\u5c0f\u5b66\u4e94\u5e74\u7ea7\u5965\u585e\u7684\u65f6\u5019\u5c31\u73a9\u817b\u7684\uff0c\u771f\u4e22\u300c\u7406\u79d1\u751f\u300d\u7684\u8138\u3002\n0x00 \u8d77\u56e0 \u672c\u7740\u5584\u5f85\u63a5\u7eb3\u7684\u6001\u5ea6\uff0c\ud83d\ude02\u8fd9\u4eba\u6015\u4e0d\u662f\u521a\u5165\u8ba1\u7b97\u673a\u7cfb\u7684\u5927\u4e00\u65b0\uff08la\uff09\u751f\uff08ji\uff09\u5427\u3002\n\u5f53\u573a\u5206\u624b +1\u3002\n0x01 \u52a8\u624b \u4ee3\u7801\u4f18\u96c5\u4e0e\u5426\u5e76\u4e0d\u662f\u91cd\u70b9=\u3002=\u771f\u6b63\u7684\u79c0\uff0c\u8981\u8ba9\u5bf9\u9762\u4e0d\u61c2\u4ee3\u7801\u7684\u4eba\u80fd\u770b\u5f97\u660e\u767d\u6548\u679c\uff0c\u5e76\u4e14\u89c9\u5f97\u4f60\u5199\u7684\u6709\u300c\u5375\u300d\u7528\u3002\n\u4e0d\u8003\u8651\u4ec0\u4e48\u300c\u8bbe\u8ba1\u6a21\u5f0f\u300d\u3001\u300c\u4f9d\u8d56\u6ce8\u5165\u300d\u3001\u300c\u6700\u4f73\u5b9e\u8df5\u300d\u4e4b\u7c7b\u7684\uff0c\u52b3\u8d44\u6572\u4ee3\u7801\u5c31\u662f\u4e00\u628a\u68ad\uff01\n# -*- coding: utf-8 -*- from PIL import Image codeLib = &#39;&#39;&#39;@B%8&amp;WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft\/\\|()1{}[]?-_+~&lt;&gt;i!lI;:,&#34;^`&#39;. &#39;&#39;&#39; # \u751f\u6210\u5b57\u7b26\u753b\u6240\u9700\u7684\u5b57\u7b26\u96c6 count = len(codeLib) def transform(image_file): image_file = image_file.convert(&#34;L&#34;) # \u8f6c\u6362\u4e3a\u9ed1\u767d\u56fe\u7247\uff0c\u53c2\u6570&#34;L&#34;\u8868\u793a\u9ed1\u767d\u6a21\u5f0f codePic = &#39;&#39; for h in range(0, image_file.size[1]): # size\u5c5e\u6027\u8868\u793a\u56fe\u7247\u7684\u5206\u8fa8\u7387\uff0c&#39;0&#39;\u4e3a\u6a2a\u5411\u5927\u5c0f\uff0c&#39;1&#39;\u4e3a\u7eb5\u5411 for w in range(0, image_file.size[0]): # \u8fd4\u56de\u6307\u5b9a\u4f4d\u7f6e\u7684\u50cf\u7d20\uff0c\u5982\u679c\u6240\u6253\u5f00\u7684\u56fe\u50cf\u662f\u591a\u5c42\u6b21\u7684\u56fe\u7247\uff0c\u90a3\u8fd9\u4e2a\u65b9\u6cd5\u5c31\u8fd4\u56de\u4e00\u4e2a\u5143\u7ec4 gray = image_file.getpixel((w, h)) codePic = codePic + \\ codeLib[int(((count-1)*gray)\/256)] # \u5efa\u7acb\u7070\u5ea6\u4e0e\u5b57\u7b26\u96c6\u7684\u6620\u5c04 codePic = codePic + &#39;\\r\\n&#39; return codePic fp = open(u&#39;my-lover.jpg&#39;, &#39;rb&#39;) image_file = Image.open(fp) image_file = image_file.resize( (int(image_file.size[0]), int(image_file.size[1]*0.4))) # \u8c03\u6574\u56fe\u5bbd\u9ad8\u6bd4\u4f8b print u&#39;Info:&#39;, image_file.size[0], &#39; &#39;, image_file.size[1] result = open(&#39;result.txt&#39;, &#39;w&#39;) result.write(transform(image_file)) result.close()  \u4ee5\u4e0a\u4ee3\u7801\u4fee\u6539\u81ea\uff1ahttps:\/\/blog.csdn.net\/wait_nothing_alone\/article\/details\/52901531\n 0x02 \u6548\u679c 0x03 \u79c0 ","permalink":"https:\/\/wi1dcard.dev\/posts\/image-to-ascii-art\/","summary":"<p>\u8981\u8d70\u521b\u610f\u8def\u7ebf\u597d\u5417\uff01<code>print \u6211\u7231\u4f60<\/code> \u4e4b\u6d41\u6015\u4e0d\u662f\u5728\u5c0f\u5b66\u4e94\u5e74\u7ea7\u5965\u585e\u7684\u65f6\u5019\u5c31\u73a9\u817b\u7684\uff0c\u771f\u4e22\u300c\u7406\u79d1\u751f\u300d\u7684\u8138\u3002<\/p>","title":"\u662f\u65f6\u5019\u79c0\u4e00\u6ce2\u771f\u6b63\u7684\u6069\u7231\u4e86"},{"content":"\u53c8\u662f\u9879\u76ee\u6240\u9700\uff0c\u7ee7\u7eed\u9020\u8f6e\u5b50\u3002\u66ff\u6362\u6307\u5b9a\u6570\u636e\u5e93\u7684\u300c\u6240\u6709\u8868\u300d\u5185\u300c\u6240\u6709\u8bb0\u5f55\u300d\u7684\u300c\u6240\u6709\u5b57\u6bb5\u300d\u7684\u503c\uff0c\u4ee5\u4e0b\u4e3a SQL \u8bed\u53e5\u3002\n0x00 \u521b\u5efa\u5b58\u50a8\u8fc7\u7a0b CREATE PROCEDURE `replace_table` (IN `orig_str` VARCHAR(100), IN `new_str` VARCHAR(100), IN `db_name` VARCHAR(100), IN `t_name` VARCHAR(100)) BEGIN DECLARE cul_name VARCHAR(100); DECLARE done int default 0; DECLARE cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA=db_name and TABLE_NAME=t_name; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN cur; FETCH cur INTO cul_name; WHILE (done&lt;&gt;1) DO # MySQL 8.0 \u4ea6\u53ef\u4f7f\u7528 REGEXP_REPLACE \u51fd\u6570\u652f\u6301\u6b63\u5219\u66ff\u6362 SET @update_sql = CONCAT(&#34;UPDATE `&#34;, t_name, &#34;` SET `&#34;, cul_name, &#34;` = REPLACE(`&#34;, cul_name, &#34;`, &#39;&#34;, orig_str, &#34;&#39;, &#39;&#34;, new_str, &#34;&#39;)&#34;, &#34; WHERE `&#34;, cul_name, &#34;` REGEXP &#39;&#34; , &#34;.*&#34; , &#34;&#39;;&#34;); # \u8f93\u51fa\u66ff\u6362 SQL -- SELECT @update_sql;  # \u6267\u884c\u66ff\u6362 SQL PREPARE stmt FROM @update_sql; EXECUTE stmt; FETCH cur INTO cul_name; END WHILE; CLOSE cur; END; CREATE PROCEDURE `replace_db` (IN orig_str VARCHAR(100), IN new_str VARCHAR(100), IN db_name VARCHAR(100), IN tbl_name VARCHAR(100)) BEGIN DECLARE t_name VARCHAR(100); DECLARE done INT DEFAULT 0; DECLARE cur CURSOR FOR SELECT DISTINCT table_name AS name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=db_name AND table_name LIKE tbl_name; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN cur; FETCH cur INTO t_name; WHILE (done&lt;&gt;1) DO CALL replace_table(orig_str, new_str, db_name, t_name); FETCH cur INTO t_name; END WHILE; END; 0x01 \u8c03\u7528 CALL replace_db(&#39;&lt;KEYWORD&gt;&#39;, &#39;&lt;REPLACE_TO&gt;&#39;, &#39;&lt;DB_NAME&gt;&#39;, &#39;&lt;TBL_NAME&gt;&#39;);  &lt;KEYWORD&gt;\uff1a\u88ab\u66ff\u6362\u7684\u5b57\u7b26\u4e32\uff0c\u5982\uff1axkedou.cn &lt;REPLACE_TO&gt;\uff1a\u66ff\u6362\u503c\uff0c\u5982\uff1azjhejiang.com &lt;DB_NAME&gt;\uff1a\u6570\u636e\u5e93\u540d\uff0c\u5982\uff1azjhj_mall &lt;TBL_NAME&gt;\uff1a\u8868\u540d\uff0c\u5982\uff1ahjmall_% \u6307\u5b9a\u8868\u524d\u7f00\u3002  \u4ee5\u4e0a\u793a\u4f8b\u53c2\u6570\u53ef\u5b9e\u73b0\uff1a\u5c06 zjhj_mall \u6570\u636e\u5e93\u5185\u6240\u6709\u524d\u7f00\u4e3a hjmall_ \u7684\u8868\u5185\u4efb\u4f55\u5b57\u6bb5\u51fa\u73b0\u7684 xkedou.cn \u5168\u90e8\u66ff\u6362\u4e3a zjhejiang.com\u3002\n\u53e6\u9644\u6b63\u5219\u66ff\u6362\u56fe\u7247\u57df\u540d\u5b9e\u4f8b\uff1a\nSELECT REGEXP_REPLACE ( &#39;http:\/\/foo.bar.com\/addons\/zjhj_mall\/core\/web\/uploads\/example.png&#39;, &#39;^(http|https):\/\/foo.bar.com\/(.*)(\\.png|\\.jpg|\\.gif|\\.jpeg)$&#39;, &#39;$1:\/\/bar.foo.com\/$2$3&#39; ); ","permalink":"https:\/\/wi1dcard.dev\/posts\/mysql-replace-text-in-all-fields\/","summary":"\u53c8\u662f\u9879\u76ee\u6240\u9700\uff0c\u7ee7\u7eed\u9020\u8f6e\u5b50\u3002\u66ff\u6362\u6307\u5b9a\u6570\u636e\u5e93\u7684\u300c\u6240\u6709\u8868\u300d\u5185\u300c\u6240\u6709\u8bb0\u5f55\u300d\u7684\u300c\u6240\u6709\u5b57\u6bb5\u300d\u7684\u503c\uff0c\u4ee5\u4e0b\u4e3a SQL \u8bed\u53e5\u3002\n0x00 \u521b\u5efa\u5b58\u50a8\u8fc7\u7a0b CREATE PROCEDURE `replace_table` (IN `orig_str` VARCHAR(100), IN `new_str` VARCHAR(100), IN `db_name` VARCHAR(100), IN `t_name` VARCHAR(100)) BEGIN DECLARE cul_name VARCHAR(100); DECLARE done int default 0; DECLARE cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.","title":"MySQL \u5728\u6240\u6709\u5b57\u6bb5\u5185\u641c\u7d22\u66ff\u6362\u6587\u672c"},{"content":"PHP has a very handy function to convert relative pathnames to absolute paths: realpath(). However, it\u2019s limited in at least two aspects which both make it inconvenient (and sometimes impossible) to use:\n It\u2019s limited to current directory \u2013 you cannot specify an arbitrary path for \u00ab.\u00bb. This is inconvenient because we don\u2019t want to change CWD before each call to realpath() and restore it afterwards. It works on already existing paths and files \u2013 this is because realpath() also resolves symlinks to real paths. However, this is much more annoying \u2013 what if we\u2019re try to get a path for a new file we\u2019re going to create? realpath() does a good job by resolving symlinks but it shouldn\u2019t fail once it finds there\u2019s no path below.  After struggling for some time with realpath() I decided to write my own function to expand relative paths to absolute \u2013 and here it is :)\n It doesn\u2019t depend on CWD, you can pass an arbitrary value for it. Two functions: Expand which works exactly like realpath() but without its downsides; and ExpandLeaveLinks which does the same but doesn\u2019t resolve symlinks. It works regardless if file\/directory exists or not. If yes (and you\u2019re not calling ExpandLeaveLinks but Expand), it will resolve symlinks until path exists. If no, it will skip the remaining path and leave it as is.  \/* RealPath() alternative - converts absolute path into relative. No license (pubilc domain). Written by Proger_XP, http:\/\/proger.i-forge.net\/Real_realpath *\/ \/\/ path w\/o trailing slash unless it&#39;s just &#34;\/&#34; or &#34;c:\/&#34;; converts \\ to \/ removing \/\/ successive \/ and \\; resolves &#39;.&#39; and &#39;..&#39; relative to $cwd. function Expand($path, $cwd = null) { $path = self::ExpandLeaveLinks($path, $cwd); if (function_exists(&#39;readlink&#39;)) { \/\/ prior to PHP 5.3 it only works for *nix.  while (is_link($path) and ($target = readlink($path)) !== false) { $path = $target; } } return $path; } function ExpandLeaveLinks($path, $cwd = null) { if (!is_scalar($path) and $path !== null) { return; } $cwd === null and $cwd = getcwd(); $cwd = static::pathize($cwd); $path = strtr($path, DS === &#39;\\\\&#39; ? &#39;\/&#39; : &#39;\\\\&#39;, DS); $firstIsSlash = (isset($path[0]) and strpbrk($path[0], &#39;\\\\\/&#39;)); if ($path === &#39;&#39; or (!$firstIsSlash and isset($path[1]) and $path[1] !== &#39;:&#39;)) { $path = $cwd.DS.$path; } elseif ($firstIsSlash and isset($cwd[1]) and $cwd[1] === &#39;:&#39;) { \/\/ when a drive is specified in CWD then \\ or \/ refers to that drive&#39;s root.  $path = substr($cwd, 0, 2).$path; } if ($path !== &#39;&#39; and ($path[0] === DS or (isset($path[1]) and $path[1] === &#39;:&#39;))) { list($prefix, $path) = explode(DS, $path, 2); $prefix .= DS; } else { $prefix = &#39;&#39;; } $expanded = array(); foreach (explode(DS, $path) as $dir) { if ($dir === &#39;..&#39;) { array_pop($expanded); } elseif ($dir !== &#39;&#39; and $dir !== &#39;.&#39;) { $expanded[] = $dir; } } return $prefix.join(DS, $expanded); } \u539f\u6587\u5730\u5740\uff1ahttp:\/\/proger.i-forge.net\/Real_realpath\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-true-realpath\/","summary":"PHP has a very handy function to convert relative pathnames to absolute paths: realpath(). However, it\u2019s limited in at least two aspects which both make it inconvenient (and sometimes impossible) to use:","title":"PHP \u76f8\u5bf9\u8def\u5f84\u8f6c\u7edd\u5bf9\u8def\u5f84"},{"content":"\u8fd1\u671f\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u6709\u4e00\u5904\u573a\u666f\u9700\u8981\u4f7f\u7528 json_encode \u65b9\u6cd5\u5e8f\u5217\u5316\u67d0\u5bf9\u8c61\u5185\u7684 protected \u5c5e\u6027\u3002\n0x00 \u5b9e\u73b0 \u8c08\u5230 json_encode \u81ea\u7136\u60f3\u5230 &lt;code&gt;JsonSerializable&lt;\/code&gt; \u63a5\u53e3\uff0c\u6b64\u63a5\u53e3\u63d0\u4f9b\u4e00\u4e2a\u62bd\u8c61\u65b9\u6cd5\uff1a\nabstract public mixed JsonSerializable::jsonSerialize ( void ) \u4e8e\u662f\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9e\u73b0\uff1a\nclass Foo implements \\JsonSerializable { public $fooProperty; protected $barProperty; public function jsonSerialize() { return [ &#39;fooProperty&#39; =&gt; $this-&gt;fooProperty, &#39;barProperty&#39; =&gt; $this-&gt;barProperty, ]; } } 0x01 \u4f18\u96c5 \u7136\u800c\u6211\u5e76\u4e0d\u6ee1\u8db3\u5982\u4e0a\u7684\u5b9e\u73b0\uff0c\u611f\u89c9\u592a\u4e0d\u4f18\u96c5\u2014\u2014\u4fee\u6539\u3001\u589e\u52a0\u5c5e\u6027\u90fd\u9700\u8981\u6539\u4e24\u5904\uff0c\u4ee3\u7801\u5f3a\u8feb\u75c7\u8868\u793a\u975e\u5e38\u53d7\u4e0d\u4e86\u3002\n\u540e\u6765\u7ecf\u8fc7 Google\uff0c\u53d1\u73b0 PHP \u6709\u4e2a\u300c\u795e\u5947\u300d\u7684\u51fd\u6570\uff1aget_object_vars\uff0c\u5982\u4e0a\u4ee3\u7801\u7a0d\u52a0\u4fee\u6539\u5373\u53ef\uff1a\nclass Foo implements \\JsonSerializable { public $fooProperty; protected $barProperty; public function jsonSerialize() { return get_object_vars($this); } } \u5b8c\u7f8e\uff01\n0x02 \u5c0f\u7ed3 \u559c\u6b22 PHP \u7684\u5176\u4e2d\u4e00\u4e2a\u539f\u56e0\uff1a\u7531\u4e8e\u539f\u751f\u7684\u5f31\u7c7b\u578b\u3001Associate \u6570\u7ec4\u7b49\u7279\u6027\uff0c\u652f\u6491\u8d77\u4e0d\u5c11\u8fd9\u79cd\u770b\u8d77\u6765\u5f88\u300c\u795e\u5947\u300d\u7684\u51fd\u6570\u7684\u5b58\u5728\uff0c\u5bf9\u4e8e\u672c\u8eab\u6bd4\u8f83\u559c\u6b22\u9075\u5faa\u89c4\u8303\u5f00\u53d1\u7684 Coders \u6765\u8bf4\uff0c\u76f8\u6bd4 .NET \u7684\u300c\u7e41\u590d\u4f18\u96c5\u300d\uff0c\u5728\u4e1a\u52a1\u5c42\u9762\u6709\u8fd9\u4e9b Helpers \u7684\u52a0\u6301\uff0c\u7b80\u76f4\u53ef\u4ee5\u8bf4\u5982\u9c7c\u5f97\u6c34\uff0c\u80fd\u591f\u7f29\u77ed\u4e0d\u5c11\u5f00\u53d1\u5468\u671f\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/json-encode-non-public-properties\/","summary":"\u8fd1\u671f\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u6709\u4e00\u5904\u573a\u666f\u9700\u8981\u4f7f\u7528 json_encode \u65b9\u6cd5\u5e8f\u5217\u5316\u67d0\u5bf9\u8c61\u5185\u7684 protected \u5c5e\u6027\u3002\n0x00 \u5b9e\u73b0 \u8c08\u5230 json_encode \u81ea\u7136\u60f3\u5230 &lt;code&gt;JsonSerializable&lt;\/code&gt; \u63a5\u53e3\uff0c\u6b64\u63a5\u53e3\u63d0\u4f9b\u4e00\u4e2a\u62bd\u8c61\u65b9\u6cd5\uff1a\nabstract public mixed JsonSerializable::jsonSerialize ( void ) \u4e8e\u662f\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9e\u73b0\uff1a","title":"json_encode() \u5e8f\u5217\u5316\u975e\u516c\u5f00\u5c5e\u6027"},{"content":"\u5728\u4f7f\u7528 C# \u7684\u8fc7\u7a0b\u4e2d\uff0c\u51e0\u4e4e\u53ef\u4ee5\u5168\u7a0b\u53ea\u9760 MSDN\uff0c\u5f88\u591a\u65b9\u6cd5\u5fae\u8f6f\u5728 .NET \u5185\u5c01\u88c5\u4e86\u5f88\u89c4\u8303\u7684\u5b9e\u73b0\uff1b\u800c\u8fd1\u671f\u5728\u4f7f\u7528 PHP \u5f00\u53d1\u9879\u76ee\u65f6\u9047\u5230\u4e2a\u5c0f\u95ee\u9898\uff1a\u83b7\u53d6\u6587\u4ef6\u6216\u76ee\u5f55 A \u76f8\u5bf9\u4e0e B \u7684\u8def\u5f84\uff0c\u7ffb\u4e86\u4e0b PHP Manual \u53d1\u73b0 PHP \u5185\u6838\u5e76\u6ca1\u6709\u63d0\u4f9b\u5b98\u65b9\u5b9e\u73b0\uff0c\u4e8e\u662f\u8c37\u6b4c\u4e4b\uff0c\u627e\u5230\u4e00\u4efd\u6bd4\u8f83\u89c4\u8303\u7684\u5b9e\u73b0\uff0c\u5728\u6b64\u8bb0\u5f55\uff0c\u4ee5\u5907\u67e5\u8be2\u3002\n0x00 \u539f\u6587 https:\/\/stackoverflow.com\/questions\/2637945\/getting-relative-path-from-absolute-path-in-php\n0x01 \u4ee3\u7801 function getRelativePath($from, $to) { \/\/ some compatibility fixes for Windows paths  $from = is_dir($from) ? rtrim($from, &#39;\\\/&#39;) . &#39;\/&#39; : $from; $to = is_dir($to) ? rtrim($to, &#39;\\\/&#39;) . &#39;\/&#39; : $to; $from = str_replace(&#39;\\\\&#39;, &#39;\/&#39;, $from); $to = str_replace(&#39;\\\\&#39;, &#39;\/&#39;, $to); $from = explode(&#39;\/&#39;, $from); $to = explode(&#39;\/&#39;, $to); $relPath = $to; foreach($from as $depth =&gt; $dir) { \/\/ find first non-matching dir  if($dir === $to[$depth]) { \/\/ ignore this directory  array_shift($relPath); } else { \/\/ get number of remaining dirs to $from  $remaining = count($from) - $depth; if($remaining &gt; 1) { \/\/ add traversals up to first matching dir  $padLength = (count($relPath) + $remaining - 1) * -1; $relPath = array_pad($relPath, $padLength, &#39;..&#39;); break; } else { $relPath[0] = &#39;.\/&#39; . $relPath[0]; } } } return implode(&#39;\/&#39;, $relPath); } 0x02 \u7528\u4f8b $a=&#34;\/home\/a.php&#34;; $b=&#34;\/home\/root\/b\/b.php&#34;; echo getRelativePath($a,$b), PHP_EOL; \/\/ .\/root\/b\/b.php  $a=&#34;\/home\/apache\/a\/a.php&#34;; $b=&#34;\/home\/root\/b\/b.php&#34;; echo getRelativePath($a,$b), PHP_EOL; \/\/ ..\/..\/root\/b\/b.php  $a=&#34;\/home\/root\/a\/a.php&#34;; $b=&#34;\/home\/apache\/htdocs\/b\/en\/b.php&#34;; echo getRelativePath($a,$b), PHP_EOL; \/\/ ..\/..\/apache\/htdocs\/b\/en\/b.php  $a=&#34;\/home\/apache\/htdocs\/b\/en\/b.php&#34;; $b=&#34;\/home\/root\/a\/a.php&#34;; echo getRelativePath($a,$b), PHP_EOL; \/\/ ..\/..\/..\/..\/root\/a\/a.php 0x03 \u5c0f\u7ed3 \u5c45\u7136\u8fd8\u6709\u4eba\u5bf9\u51e0\u4e2a\u56de\u7b54\u505a\u4e86\u603b\u7ed3\u5bf9\u6bd4\u548c\u65f6\u95f4\u590d\u6742\u5ea6\u8bc4\u6d4b\ud83d\ude02\uff0c\u771f\u662f 666\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-getting-releative-path\/","summary":"\u5728\u4f7f\u7528 C# \u7684\u8fc7\u7a0b\u4e2d\uff0c\u51e0\u4e4e\u53ef\u4ee5\u5168\u7a0b\u53ea\u9760 MSDN\uff0c\u5f88\u591a\u65b9\u6cd5\u5fae\u8f6f\u5728 .NET \u5185\u5c01\u88c5\u4e86\u5f88\u89c4\u8303\u7684\u5b9e\u73b0\uff1b\u800c\u8fd1\u671f\u5728\u4f7f\u7528 PHP \u5f00\u53d1\u9879\u76ee\u65f6\u9047\u5230\u4e2a\u5c0f\u95ee\u9898\uff1a\u83b7\u53d6\u6587\u4ef6\u6216\u76ee\u5f55 A \u76f8\u5bf9\u4e0e B \u7684\u8def\u5f84\uff0c\u7ffb\u4e86\u4e0b PHP Manual \u53d1\u73b0 PHP \u5185\u6838\u5e76\u6ca1\u6709\u63d0\u4f9b\u5b98\u65b9\u5b9e\u73b0\uff0c\u4e8e\u662f\u8c37\u6b4c\u4e4b\uff0c\u627e\u5230\u4e00\u4efd\u6bd4\u8f83\u89c4\u8303\u7684\u5b9e\u73b0\uff0c\u5728\u6b64\u8bb0\u5f55\uff0c\u4ee5\u5907\u67e5\u8be2\u3002\n0x00 \u539f\u6587 https:\/\/stackoverflow.com\/questions\/2637945\/getting-relative-path-from-absolute-path-in-php","title":"PHP \u5b9e\u73b0\u7c7b\u4f3c C# MakeRelativeUri \u65b9\u6cd5"},{"content":"\u6700\u8fd1\u4ece\u524d\u516c\u53f8\u79bb\u804c\uff0c\u5185\u5fc3\u8868\u793a\u5f88\u75db\uff0c\u81ea\u5df1\u4e4b\u524d\u7684\u6280\u672f\u6587\u7ae0\u8fd8\u90fd\u5728\u56e2\u961f\u535a\u5ba2\u90a3\u8fb9\uff0c\u5c06\u8fd1\u4e00\u5e74\u7684\u6210\u679c\u4e0d\u80fd\u5c31\u8fd9\u4e48\u653e\u5f03\uff0c\u4e8e\u662f\u5f00\u59cb\u6298\u817e\u8f6c\u79fb\u3002\n\u9996\u5148\u8003\u8651\u4e86\u4e00\u4e0b\u5404\u8def\u52a8\u6001\u535a\u5ba2\u7cfb\u7edf\uff0c\u5165\u773c\u7684\u53ea\u6709 Typecho\uff1b\u60f3\u4e86\u4e00\u4e0b\uff0c\u611f\u89c9\u518d\u642d\u4e2a\u73af\u5883\u592a\u9ebb\u70e6\uff0c\u8fd8\u8981\u8c03\u4f18\u3001\u52a0 CDN\u3001\u4fdd\u8bc1\u8bbf\u95ee\u901f\u5ea6\u4ec0\u4e48\u7684\u2026\u2026\u5e72\u8106\u4e00\u4e0d\u505a\u4e8c\u4e0d\u4f11\uff0c\u56de\u5f52\u6781\u7b80\u98ce\u683c\uff0c\u7528\u7eaf\u9759\u6001 + GitHub Pages\u3002\n\u4e8e\u662f\uff0c\u4f60\u73b0\u5728\u770b\u5230\u7684\u4e1c\u897f\u8bde\u751f\u4e86\u3002\n\u4e4b\u524d\u7684\u90fd\u8ba9\u5b83\u8fc7\u53bb\u5427\u3002\n\u6211\u4f1a\u7ee7\u7eed\u52aa\u529b\u7684\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/blog-migrated\/","summary":"\u6700\u8fd1\u4ece\u524d\u516c\u53f8\u79bb\u804c\uff0c\u5185\u5fc3\u8868\u793a\u5f88\u75db\uff0c\u81ea\u5df1\u4e4b\u524d\u7684\u6280\u672f\u6587\u7ae0\u8fd8\u90fd\u5728\u56e2\u961f\u535a\u5ba2\u90a3\u8fb9\uff0c\u5c06\u8fd1\u4e00\u5e74\u7684\u6210\u679c\u4e0d\u80fd\u5c31\u8fd9\u4e48\u653e\u5f03\uff0c\u4e8e\u662f\u5f00\u59cb\u6298\u817e\u8f6c\u79fb\u3002\n\u9996\u5148\u8003\u8651\u4e86\u4e00\u4e0b\u5404\u8def\u52a8\u6001\u535a\u5ba2\u7cfb\u7edf\uff0c\u5165\u773c\u7684\u53ea\u6709 Typecho\uff1b\u60f3\u4e86\u4e00\u4e0b\uff0c\u611f\u89c9\u518d\u642d\u4e2a\u73af\u5883\u592a\u9ebb\u70e6\uff0c\u8fd8\u8981\u8c03\u4f18\u3001\u52a0 CDN\u3001\u4fdd\u8bc1\u8bbf\u95ee\u901f\u5ea6\u4ec0\u4e48\u7684\u2026\u2026\u5e72\u8106\u4e00\u4e0d\u505a\u4e8c\u4e0d\u4f11\uff0c\u56de\u5f52\u6781\u7b80\u98ce\u683c\uff0c\u7528\u7eaf\u9759\u6001 + GitHub Pages\u3002\n\u4e8e\u662f\uff0c\u4f60\u73b0\u5728\u770b\u5230\u7684\u4e1c\u897f\u8bde\u751f\u4e86\u3002\n\u4e4b\u524d\u7684\u90fd\u8ba9\u5b83\u8fc7\u53bb\u5427\u3002\n\u6211\u4f1a\u7ee7\u7eed\u52aa\u529b\u7684\u3002","title":"\u535a\u5ba2\u8fc1\u79fb \u2014\u2014 \u5168\u65b0\u7684\u5f00\u59cb"},{"content":" \u6211\u4eec\u6700\u597d\u7684\u9047\u89c1\uff0c\u662f\u73b0\u5728\u8fd9\u6837\u7684\u516d\u6708\u3002\u6211\u4eec\u6700\u597d\u7684\u544a\u522b\uff0c\u662f\u73b0\u5728\u8fd9\u6837\u2026\u2026\n \u6ca1\u7ea2\u773c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/say-hello-to-june\/","summary":"\u6211\u4eec\u6700\u597d\u7684\u9047\u89c1\uff0c\u662f\u73b0\u5728\u8fd9\u6837\u7684\u516d\u6708\u3002\u6211\u4eec\u6700\u597d\u7684\u544a\u522b\uff0c\u662f\u73b0\u5728\u8fd9\u6837\u2026\u2026\n \u6ca1\u7ea2\u773c\u3002","title":"\u516d\u6708\uff0c\u4f60\u597d\u3002"},{"content":"\u51e0\u4e4e\u6240\u6709 Git \u5e73\u53f0\u5728 Pull request \/ Issue \u7b49\u529f\u80fd\u4e0a\u5927\u91cf\u4f7f\u7528 Markdown \u8bed\u6cd5\uff0c\u6240\u4ee5\u5728\u8fd9\u91cc\u7b80\u5355\u4ecb\u7ecd\u5e76\u7ed9\u51fa\u6548\u679c\u9884\u89c8\uff0c\u4ee5\u65b9\u4fbf\u4f7f\u7528\u3002\n \u4e00\u7ea7\u6807\u9898 \u4e8c\u7ea7\u6807\u9898 \u4e09\u7ea7\u6807\u9898 \u56db\u7ea7\u6807\u9898  \u6709\u5e8f\u5217\u8868\uff1a\n this is a test list   \u65e0\u5e8f\u5217\u8868\uff1a\n this is a test list  \u8fd8\u6709\u4e00\u79cd\u5199\u6cd5\uff1a\n this is a test list   \u6709\u5e8f\u5217\u8868\uff1a\n this is a test list  \u6709\u5e8f\u5217\u8868\u548c\u65e0\u5e8f\u5217\u8868\u4e2d\u95f4\u90fd\u53ef\u4ee5\u52a0\u4e00\u884c\u7a7a\u884c\uff0cMarkdown \u4f1a\u81ea\u52a8\u8c03\u6574\u884c\u95f4\u8ddd\u66f4\u5927\uff0c\u65b9\u4fbf\u9605\u8bfb\u3002\n  \u9ad8\u4eae  This is a example text.\n \u52a0\u7c97  This is a example text.\n \u659c\u4f53  This is a example text.\n \u5f15\u7528\uff1a   This is a example text.\n  \u5206\u5272\u7ebf\uff08\u5c31\u662f\u4e0a\u9762\u8fd9\u4e2a\uff0c\u51e0\u4e2a\u8fde\u63a5\u7b26-\uff09\n\u53e6\u5916\uff1a\n  \u4ee5\u4e0a\u8bed\u6cd5\u5168\u90e8\u53ef\u4ee5\u5d4c\u5957\u4f7f\u7528\u3002\n  \u5728\u6362\u884c\u65f6\u5fc5\u987b\u4f7f\u7528\u4e2d\u95f4\u7a7a\u4e00\u884c\u7684\u65b9\u5f0f\uff0c\u4ee5\u65b9\u4fbf\u5728\u7eaf\u6587\u672c\u6a21\u5f0f\u4e0b\u7684 Markdown \u53ef\u8bfb\u6027\u3002\n  \u5217\u8868\u3001\u6807\u9898\u7b26\u53f7\u4e4b\u540e\u5fc5\u987b\u5e26\u4e00\u4e2a\u7a7a\u683c\u518d\u5199\u6587\u672c\u3002\n  \u6269\u5c55\u9605\u8bfb\uff1ahttps:\/\/www.jianshu.com\/p\/3dbef7dd9c8e\u3001https:\/\/www.jianshu.com\/p\/468f111d8fd3\u3002\n  \u652f\u6301\u9884\u89c8\u7684\u5728\u7ebf\u7f16\u8f91\u5668\uff1ahttps:\/\/www.zybuluo.com\/mdeditor\u3002\n  ","permalink":"https:\/\/wi1dcard.dev\/posts\/markdown-syntax-intro\/","summary":"\u51e0\u4e4e\u6240\u6709 Git \u5e73\u53f0\u5728 Pull request \/ Issue \u7b49\u529f\u80fd\u4e0a\u5927\u91cf\u4f7f\u7528 Markdown \u8bed\u6cd5\uff0c\u6240\u4ee5\u5728\u8fd9\u91cc\u7b80\u5355\u4ecb\u7ecd\u5e76\u7ed9\u51fa\u6548\u679c\u9884\u89c8\uff0c\u4ee5\u65b9\u4fbf\u4f7f\u7528\u3002\n \u4e00\u7ea7\u6807\u9898 \u4e8c\u7ea7\u6807\u9898 \u4e09\u7ea7\u6807\u9898 \u56db\u7ea7\u6807\u9898  \u6709\u5e8f\u5217\u8868\uff1a\n this is a test list   \u65e0\u5e8f\u5217\u8868\uff1a","title":"Markdown \u8bed\u6cd5\u7b80\u660e\u4ecb\u7ecd"},{"content":" WDCP \u9762\u677f\u9ed8\u8ba4\u91c7\u7528 LNAMP \u7684\u7ed3\u6784\uff0c\u5373 Nginx \u5904\u7406\u9759\u6001\u9875\u9762\uff0c\u5e76\u8f6c\u53d1\u52a8\u6001\u811a\u672c\u8bf7\u6c42\uff08\u5982 PHP\uff09\u5230 Apache \u5904\u7406\u3002\u8fd9\u5728\u6ca1\u6709 PHP-FPM \u7684\u65f6\u4ee3\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\uff0c\u4f46\u82e5\u662f\u914d\u7f6e\u4e0d\u5f53\uff0c\u5b58\u5728\u7684\u95ee\u9898\u4e5f\u5f88\u660e\u663e\uff0c\u8fd9\u5c31\u662f\u4e00\u4f8b\u3002\n 0x00 \u80cc\u666f \u6700\u8fd1\u4f7f\u7528 Yii2 \u6846\u67b6\u5f00\u53d1\u7684\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u5728 WDCP \u9762\u677f\u7684\u73af\u5883\u4e0b\uff0cYii \u81ea\u5e26\u7684 yii\\web\\Request::getIsSecureConnection \u5e76\u4e0d\u80fd\u6709\u6548\u5224\u65ad\u5176\u662f\u5426\u662f HTTPS \u8bf7\u6c42\u3002\n0x01 \u731c\u6d4b \u51ed\u76f4\u89c9\u5224\u65ad\uff0c\u662f\u7531\u4e8e\u8bf7\u6c42\u5904\u7406\u7684\u8fc7\u7a0b\u4e2d\uff0cHTTPS \u8bc1\u4e66\u89e3\u6790\u5728 Nginx \u5c42\u9762\u5df2\u7ecf\u5904\u7406\u6389\uff0c\u6ca1\u6709\u8f6c\u53d1\u7ed9 Apache\uff0c\u5e76\u4e14\u53ef\u80fd\u7531\u4e8e WDCP \u9762\u677f\u914d\u7f6e\u4e0d\u5f53\u5bfc\u81f4\u8f6c\u53d1\u65f6\u672a\u643a\u5e26 HTTP_X_FORWARDED_PROTO \u534f\u8bae\u5934\u3002\n0x02 \u5c1d\u8bd5 \u6545\u67e5\u627e WDCP \u914d\u7f6e\uff0c\u7ecf\u8fc7\u4e00\u756a\u641c\u7d22\uff0c\u6b64 Nginx \u914d\u7f6e\u6587\u4ef6\u4f4d\u4e8e\uff1a\/www\/wdlinux\/nginx\/conf\/naproxy.conf\u3002\n\u5728\u6b64\u6587\u4ef6\u5185\u8ffd\u52a0\u4e00\u884c\uff1a\nproxy_set_header X-Forwarded-Proto $scheme; \u95ee\u9898\u89e3\u51b3\u3002\n0x03 \u611f\u6168 \u5982\u4eca\u8fd9\u65f6\u4ee3\uff0c\u80fd\u7528 PHP-FPM\uff0c\u8fd8\u662f\u522b N+A \u4e86\u5427\u3002\u51fa\u529b\u4e0d\u8ba8\u597d\u3002\nN+A\uff1f\uff01\uff1f\u4e3a\u4ec0\u4e48\u83ab\u540d\u60f3\u5230\u2026\u2026N \u5361 A \u5361\u2026\u2026\n","permalink":"https:\/\/wi1dcard.dev\/posts\/wdcp-lnamp-https-detecting-issue\/","summary":"WDCP \u9762\u677f\u9ed8\u8ba4\u91c7\u7528 LNAMP \u7684\u7ed3\u6784\uff0c\u5373 Nginx \u5904\u7406\u9759\u6001\u9875\u9762\uff0c\u5e76\u8f6c\u53d1\u52a8\u6001\u811a\u672c\u8bf7\u6c42\uff08\u5982 PHP\uff09\u5230 Apache \u5904\u7406\u3002\u8fd9\u5728\u6ca1\u6709 PHP-FPM \u7684\u65f6\u4ee3\u662f\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\uff0c\u4f46\u82e5\u662f\u914d\u7f6e\u4e0d\u5f53\uff0c\u5b58\u5728\u7684\u95ee\u9898\u4e5f\u5f88\u660e\u663e\uff0c\u8fd9\u5c31\u662f\u4e00\u4f8b\u3002\n 0x00 \u80cc\u666f \u6700\u8fd1\u4f7f\u7528 Yii2 \u6846\u67b6\u5f00\u53d1\u7684\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u5728 WDCP \u9762\u677f\u7684\u73af\u5883\u4e0b\uff0cYii \u81ea\u5e26\u7684 yii\\web\\Request::getIsSecureConnection \u5e76\u4e0d\u80fd\u6709\u6548\u5224\u65ad\u5176\u662f\u5426\u662f HTTPS \u8bf7\u6c42\u3002","title":"\u4fee\u590d WDCP \u9762\u677f\u65e0\u6cd5\u5224\u65ad HTTPS \u7684\u95ee\u9898"},{"content":" \u5988\u5988\u518d\u4e5f\u4e0d\u7528\u62c5\u5fc3\u6eda\u52a8\u622a\u56fe\u548c\u622a\u56fe\u8fb9\u6846\u4e86\uff5e\n 0x00 \u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u5148\u4e0a\u6548\u679c\u56fe\uff1a\n0x01 \u5176\u5b9e\u8fd9\u662f\u4e00\u6b3e VS Code \u7684\u63d2\u4ef6\uff0c\u53ea\u9700\u8981\u5728 VS Code \u5185\u5b89\u88c5\u5373\u53ef\u3002\n\u4f7f\u7528\u65b9\u6cd5\u6bd4\u8f83\u7b80\u5355\uff0c\u9996\u5148\u4f7f\u7528\u5feb\u6377\u952e Shift + Command + P \u8c03\u51fa\u547d\u4ee4\u7a97\u53e3\uff0c\u7136\u540e\u8f93\u5165 Polacode \u56de\u8f66\u3002\n\u5f39\u51fa\u7684\u754c\u9762\u5c31\u662f Polacode \u4e86\uff0c\u5728\u4f60\u7684\u4ee3\u7801\u6846\u91cc\u590d\u5236\u4f60\u8981\u622a\u56fe\u7684\u4ee3\u7801\uff0c\u7126\u70b9\u5207\u6362\u5230 Polacode \u540e Command + V\u3002\n\u8fd9\u65f6\u5019\u4f60\u4f1a\u53d1\u73b0\u4ee3\u7801\u5df2\u7ecf\u7c98\u8d34\u8fdb\u53bb\u4e86\uff0c\u7f8e\u6ecb\u6ecb\uff0c\u800c\u4e14\u8fd8\u4fdd\u7559\u7740\u4f60\u4e3b\u9898\u7684\u989c\u8272\u548c\u683c\u5f0f\uff1b\u62c9\u5230\u6700\u4e0b\u9762\uff0c\u5355\u51fb\u5feb\u95e8\u56fe\u6807\u4fdd\u5b58\u5373\u53ef\u3002\n0x02 \u6700\u540e\uff0c\u521d\u6b21\u4f7f\u7528\u8fd9\u4e2a\u63d2\u4ef6\u7684\u65f6\u5019\u6709\u4e2a BUG\uff0c\u7c98\u8d34\u4e4b\u540e\u5bbd\u5ea6\u8d85\u51fa Polacode \u8fb9\u6846\u5bbd\u5ea6\uff0c\u663e\u5f97\u975e\u5e38\u96be\u770b\uff0c\u7ffb\u9605\u6587\u6863\u540e\u53d1\u73b0\u6709\u8fd9\u4e48\u4e00\u53e5\uff1a\n When running out of horizontal space, try the command View: &gt; Toggle Editor Group Vertical\/Horizontal Layout.\n \u4e8e\u662f\u6309\u7167\u6b65\u9aa4\u5c06\u7f16\u8f91\u5668\u5207\u6362\u4e3a\u5782\u76f4\u5e03\u5c40\u5373\u53ef\uff0c\u8fd9\u6837\u8c03\u51fa Polacode \u7684\u65f6\u5019\u5c31\u4f1a\u662f\u5782\u76f4\u5207\u5206\u7684\u4e24\u4e2a\u7a97\u53e3\uff0c\u5982\u4e0b\u56fe\uff1a\n\u95ee\u9898\u89e3\u51b3\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/vscode-polacode\/","summary":"\u5988\u5988\u518d\u4e5f\u4e0d\u7528\u62c5\u5fc3\u6eda\u52a8\u622a\u56fe\u548c\u622a\u56fe\u8fb9\u6846\u4e86\uff5e\n 0x00 \u5e9f\u8bdd\u4e0d\u591a\u8bf4\uff0c\u5148\u4e0a\u6548\u679c\u56fe\uff1a\n0x01 \u5176\u5b9e\u8fd9\u662f\u4e00\u6b3e VS Code \u7684\u63d2\u4ef6\uff0c\u53ea\u9700\u8981\u5728 VS Code \u5185\u5b89\u88c5\u5373\u53ef\u3002\n\u4f7f\u7528\u65b9\u6cd5\u6bd4\u8f83\u7b80\u5355\uff0c\u9996\u5148\u4f7f\u7528\u5feb\u6377\u952e Shift + Command + P \u8c03\u51fa\u547d\u4ee4\u7a97\u53e3\uff0c\u7136\u540e\u8f93\u5165 Polacode \u56de\u8f66\u3002","title":"Polacode - \u751f\u6210\u4f18\u96c5\u7f8e\u89c2\u7684\u4ee3\u7801\u7247\u6bb5\u56fe"},{"content":" \u672c\u6587\u4ee5\u5b89\u88c5 mongodb \u6269\u5c55\u4e3a\u4f8b\uff0c\u7b80\u5355\u8bb2\u89e3\u4f7f\u7528 phpize \u7ed9\u591a\u7248\u672c php \u7f16\u8bd1\u5b89\u88c5\u6269\u5c55\u3002\n 0x00 \u51c6\u5907 \u5047\u8bbe\u4f60\u7684\u670d\u52a1\u5668\u6709\u591a\u4e2a\u7248\u672c php\uff0c\u4f60\u9996\u5148\u8981\u627e\u5230\u5bf9\u5e94\u7248\u672c php \u7684 phpize\u3001php-config \u7a0b\u5e8f\u3002\u901a\u5e38\u5b83\u4eec\u4e0e php \u6240\u5904\u76ee\u5f55\u76f8\u540c\u3002\n\u63a5\u4e0b\u6765\u4e0b\u8f7d\u4f60\u7684\u6269\u5c55\u6e90\u7801\u5305\uff0c\u591a\u6570\u6269\u5c55\u6e90\u7801\u90fd\u80fd\u5728 github \u6216 pecl \u4e0b\u8f7d\u5230\u3002\n\u8fd9\u91cc\u6211\u4eec\u4e0b\u8f7d mongodb \u6269\u5c55\u5e76\u89e3\u538b\uff1a\nwget http:\/\/pecl.php.net\/get\/mongodb-1.4.3.tgz tar xvzf mongodb-1.4.3.tgz \u56fd\u5185\u4e3b\u673a\u53ef\u80fd\u4f1a\u5f88\u6162\uff0c\u7b80\u6613\u79d1\u5b66\u4e0a\u7f51\u4e0b\u8f7d\u540e scp \u4f20\u4e0a\u53bb\u3002\n0x01 phpize \u6839\u636e\u524d\u9762\u5f97\u5230\u7684 phpize \u8def\u5f84\uff0c\u5728\u6269\u5c55\u7684\u6e90\u7801\u76ee\u5f55\u6267\u884c phpize \u547d\u4ee4\u5373\u53ef\uff1a\ncd mongodb-1.4.3 ..\/..\/..\/bin\/phpize 0x02 \u6b63\u5e38\u7f16\u8bd1 \u6267\u884c\u5982\u4e0b\u547d\u4ee4\u5373\u53ef\u3002\u6ce8\u610f\uff0c--with-php-config\u53c2\u6570\u9700\u8981\u6b63\u786e\u586b\u5165 php-config \u7684\u8def\u5f84\u3002\n.\/configure --with-php-config=\/usr\/local\/php-7.2\/bin\/php-config make make install \u6b63\u5e38\u8f93\u51fa\uff1a\n\u8bb0\u4e0b\u8fd9\u4e2a\u76ee\u5f55\uff0c\u4e00\u4f1a\u513f\u8fd8\u8981\u7528\u5230\u3002\n0x03 php.ini \u4fee\u6539\u5bf9\u5e94\u7684 php.ini \u6587\u4ef6\uff0c\u52a0\u5165\u6b64\u884c\uff1a\nextension=\/usr\/local\/php-7.2\/lib\/php\/extensions\/no-debug-non-zts-20170718\/mongodb.so \u5982\u679c\u6269\u5c55\u6bd4\u8f83\u591a\uff0c\u5efa\u8bae\u6574\u7406\u4e00\u4e2a\u6bd4\u8f83\u5bb9\u6613\u627e\u7684\u76ee\u5f55\uff08\u4f8b\u5982\uff1a\/usr\/local\/php\/ext\u7b49\uff09\u4e13\u95e8\u5b58\u653e\u3002\n\u6700\u540e\uff0c\u91cd\u542f php-fpm\uff0c\u5199\u4e2a phpinfo \u6d4b\u8bd5\u5427\u3002\n0x04 \u611f\u8a00 \u5c3d\u91cf\u8fd8\u662f\u7528 pecl \u5427\uff0c\u4f18\u70b9\uff1a\u65b9\u4fbf\u5347\u7ea7\uff0c\u4e5f\u53ef\u4ee5\u907f\u514d\u8def\u5f84\u6df7\u4e71\uff0c\u800c\u4e14\u8fd8\u7701\u4e8b\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/get-started-with-phpize\/","summary":"\u672c\u6587\u4ee5\u5b89\u88c5 mongodb \u6269\u5c55\u4e3a\u4f8b\uff0c\u7b80\u5355\u8bb2\u89e3\u4f7f\u7528 phpize \u7ed9\u591a\u7248\u672c php \u7f16\u8bd1\u5b89\u88c5\u6269\u5c55\u3002\n 0x00 \u51c6\u5907 \u5047\u8bbe\u4f60\u7684\u670d\u52a1\u5668\u6709\u591a\u4e2a\u7248\u672c php\uff0c\u4f60\u9996\u5148\u8981\u627e\u5230\u5bf9\u5e94\u7248\u672c php \u7684 phpize\u3001php-config \u7a0b\u5e8f\u3002\u901a\u5e38\u5b83\u4eec\u4e0e php \u6240\u5904\u76ee\u5f55\u76f8\u540c\u3002\n\u63a5\u4e0b\u6765\u4e0b\u8f7d\u4f60\u7684\u6269\u5c55\u6e90\u7801\u5305\uff0c\u591a\u6570\u6269\u5c55\u6e90\u7801\u90fd\u80fd\u5728 github \u6216 pecl \u4e0b\u8f7d\u5230\u3002","title":"phpize \u7b80\u6613\u5165\u95e8"},{"content":" \u6295\u5f71\u4eea\uff08\u7535\u89c6\uff09+\u673a\u9876\u76d2+\u97f3\u54cd\u8bbe\u5907\u63a7\u5236\u9879\u76ee\uff0c\u56e0\u81ea\u7528\u4e8e\u5ba2\u5385\u603b\u63a7\uff0c\u6545\u547d\u540d\u4e3aMediaCenter\u3002\n \u63d0\u793a\uff1a\u5f3a\u7535\u5371\u9669\uff0c\u63a5\u7ebf\u52a1\u5fc5\u6ce8\u610f\u5b89\u5168\u3002\n0x00 \u51c6\u5907 \u786c\u4ef6\uff1a\n \u6811\u8393\u6d3e 3B\u3002 \u5fae\u96ea\u7ee7\u7535\u5668\u6a21\u5757\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002 \u672a\u63a5\u7ebf\u63d2\u5ea7+\u7535\u7f06\u7ebf\u3002 \u7ea2\u5916\u5b66\u4e60\u6a21\u5757\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002 USB \u8f6c TTL\uff08PL2303\uff09\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002   \u7ee7\u7535\u5668\u6a21\u5757\u4e5f\u53ef\u4ee5\u6362\u6210\u5176\u5b83\u666e\u901a\u7ee7\u7535\u5668\uff0c\u4f7f\u7528\u6811\u8393\u6d3e GPIO \u53e3\u8f93\u51fa\u9ad8\u4f4e\u7535\u5e73\u5373\u53ef\uff0c\u6211\u91c7\u7528\u73b0\u6210\u6a21\u5757\uff0c\u4ee5\u6c42\u7a33\u5b9a\u53ef\u9760\u3002 \u7ea2\u5916\u6a21\u5757\u4e5f\u53ef\u4ee5\u76f4\u63a5\u8fde\u63a5\u6811\u8393\u6d3e UART\uff0c\u6211\u91c7\u7528\u52a0\u88c5 USB \u8f6c TTL \u6a21\u5757\uff0c\u907f\u514d\u6d6a\u8d39\u552f\u4e00\u4e00\u4e2a UART\u3002\n \u8f6f\u4ef6\uff1a\n Python 3 Laravel 5 + Composer Node.js + NPM Vue Laravel Echo Server  0x01 \u57fa\u672c\u601d\u8def  \u8fde\u63a5 PL2303 \u548c\u7ea2\u5916\u6a21\u5757\u3002 \u8fde\u63a5\u63d2\u6392\uff0c\u7834\u5f00\u706b\u7ebf\uff0c\u8fde\u63a5\u7ee7\u7535\u5668\u3002\u65e0\u5f3a\u7535\u7ecf\u9a8c\u5efa\u8bae\u54a8\u8be2\u7535\u5de5\uff0c\u4e00\u65e6\u63a5\u9519\u8f7b\u5219\u77ed\u8def\uff0c\u91cd\u5219\u8d77\u706b\uff01 \u7f16\u5199 Python \u811a\u672c\uff0c\u7528\u4e8e\u63a7\u5236\u7ee7\u7535\u5668\u3002\u4e3b\u8981\u4e3a\u64cd\u4f5c GPIO\uff0c\u8f93\u51fa\u9ad8\u4f4e\u7535\u5e73\u3002\u6e90\u7801\uff1aresource\/relay.py\u3002 \u7f16\u5199 Python \u811a\u672c\uff0c\u7528\u4e8e\u63a7\u5236\u7ea2\u5916\u6a21\u5757\u3002\u4e3b\u8981\u4e3a\u64cd\u4f5c\u4e32\u53e3\uff0c\u6839\u636e\u786c\u4ef6\u5382\u5546\u534f\u8bae\u5bf9\u63a5\u5373\u53ef\u3002\u6e90\u7801\uff1aresource\/infrared.py\u3002 \u7f16\u5199 Laravel \u63a7\u5236\u5668\u3001\u8def\u7531\uff0c\u7528\u4e8e\u8c03\u7528\u5982\u4e0a\u811a\u672c\uff1b\u4e0d\u8981\u5fd8\u8bb0\u6743\u9650\u95ee\u9898\uff0c\u9700\u8981\u5c06\u8fd0\u884c php-fpm \u7684\u7528\u6237\u6dfb\u52a0\u81f3 gpio\u3001dialout \u7528\u6237\u7ec4\uff0c\u4e14\u7ed9\u4e88\u811a\u672c\u53ef\u6267\u884c\u6743\u9650\u3002 \u4f7f\u7528 Laravel Broadcasting \u5e7f\u64ad\uff0c\u5c06\u811a\u672c\u6267\u884c\u72b6\u6001\u53d1\u9001\u5230\u5ba2\u6237\u7aef\uff0c\u8be6\u89e3\u3002 \u7f16\u5199\u524d\u7aef\uff0c\u7528\u4e8e\u5b9e\u65f6\u5c55\u793a\u3002 \u4ee3\u7801\u4e22\u5230\u6811\u8393\u6d3e\u3002  \u8be6\u7ec6\u6e90\u7801\u53ef\u53c2\u8003\u6b64\u4ed3\u5e93\u3002\n0x02 \u6548\u679c \u786c\u4ef6\uff1a\n\u7528\u7edd\u7f18\u80f6\u5e03\u8d34\u6b7b\u7ee7\u7535\u5668\u6a21\u5757\uff0c\u907f\u514d\u4e0d\u5c0f\u5fc3\u8bef\u89e6\u78b0\u3002\n\u5c0f\u63d2\u5ea7\u662f\u5e38\u7535\uff0c\u63a5\u6295\u5f71\u4eea\uff1b\u5927\u63d2\u6392\u662f\u8d70\u7ee7\u7535\u5668\u63a7\u5236\uff0c\u63a5\u97f3\u54cd\u548c\u673a\u9876\u76d2\u3002\u8fd9\u91cc\u6ca1\u6709\u628a\u5e38\u7535\u7ebf\u7834\u5f00\uff0c\u800c\u662f\u76f4\u63a5\u5728\u5e38\u7535\u63d2\u5ea7\u5185\u63a5\u51fa\u6765\u5730\u706b\u96f6\u3002\n \u63a5\u7ebf\u7a0d\u6709\u70b9\u4e71\uff0c\u51d1\u5408\u770b\u5427\uff0c\u6bd5\u7adf\u4e0d\u662f\u786c\u4ef6\u51fa\u8eab\uff0c\u5e78\u4e8f\u5c0f\u65f6\u5019\u8ddf\u6211\u7239\u5b66\u7684\u5f3a\u7535\u57fa\u7840\u6ca1\u5fd8\u5149\/\u659c\u773c\u7b11\u3002\u5c0f\u63d2\u6392\u51fa\u6765\u7684\u7ebf\u7f06\u539f\u672c\u6253\u7b97\u957f\u4e00\u70b9\uff0c\u540e\u6765\u53c8\u89c9\u5f97\u592a\u957f&hellip; \u5f88\u5c2c\u3002\n \u8f6f\u4ef6\uff1a\n\u7f51\u9875\u76f4\u63a5\u5d4c\u5165 Dashboard\u3002\n0x03 \u611f\u60f3 \u6700\u5f00\u59cb\u601d\u8003\u5982\u4f55\u4e0d\u7528\u6ee1\u5c4b\u627e\u9065\u63a7\u5668\u4e14\u4f18\u96c5\u5730\u6253\u5f00\u7535\u89c6\u8d39\u4e86\u5f88\u5927\u65f6\u95f4\uff1b\u4e3b\u8981\u95ee\u9898\u4e0d\u5728\u4e8e\u6280\u672f\u5982\u4f55\u5b9e\u73b0\uff0c\u800c\u5728\u4e8e\u5982\u4f55\u5bf9\u6211\u8fd9\u79cd\u54b8\u9c7c\u66f4\u52a0\u7b80\u5355\u5feb\u6377\u3002\u6253\u5f00\u7f51\u9875\u592a\u9ebb\u70e6\uff0c\u5ba2\u6237\u7aef\u4e0d\u591f\u201c\u7eff\u8272\u201d\uff0cAPP \u592a\u590d\u6742\uff0c\u6700\u7ec8\u53d1\u73b0 Mac Dashboard \u5c45\u7136\u80fd\u4e22\u7f51\u9875\uff0c\u5b8c\u7f8e\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-media-center\/","summary":"\u6295\u5f71\u4eea\uff08\u7535\u89c6\uff09+\u673a\u9876\u76d2+\u97f3\u54cd\u8bbe\u5907\u63a7\u5236\u9879\u76ee\uff0c\u56e0\u81ea\u7528\u4e8e\u5ba2\u5385\u603b\u63a7\uff0c\u6545\u547d\u540d\u4e3aMediaCenter\u3002\n \u63d0\u793a\uff1a\u5f3a\u7535\u5371\u9669\uff0c\u63a5\u7ebf\u52a1\u5fc5\u6ce8\u610f\u5b89\u5168\u3002\n0x00 \u51c6\u5907 \u786c\u4ef6\uff1a\n \u6811\u8393\u6d3e 3B\u3002 \u5fae\u96ea\u7ee7\u7535\u5668\u6a21\u5757\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002 \u672a\u63a5\u7ebf\u63d2\u5ea7+\u7535\u7f06\u7ebf\u3002 \u7ea2\u5916\u5b66\u4e60\u6a21\u5757\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002 USB \u8f6c TTL\uff08PL2303\uff09\uff0c\u6dd8\u5b9d\u94fe\u63a5\u3002   \u7ee7\u7535\u5668\u6a21\u5757\u4e5f\u53ef\u4ee5\u6362\u6210\u5176\u5b83\u666e\u901a\u7ee7\u7535\u5668\uff0c\u4f7f\u7528\u6811\u8393\u6d3e GPIO \u53e3\u8f93\u51fa\u9ad8\u4f4e\u7535\u5e73\u5373\u53ef\uff0c\u6211\u91c7\u7528\u73b0\u6210\u6a21\u5757\uff0c\u4ee5\u6c42\u7a33\u5b9a\u53ef\u9760\u3002 \u7ea2\u5916\u6a21\u5757\u4e5f\u53ef\u4ee5\u76f4\u63a5\u8fde\u63a5\u6811\u8393\u6d3e UART\uff0c\u6211\u91c7\u7528\u52a0\u88c5 USB \u8f6c TTL \u6a21\u5757\uff0c\u907f\u514d\u6d6a\u8d39\u552f\u4e00\u4e00\u4e2a UART\u3002","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0\u2014\u2014\u7ee7\u7535\u5668+\u7ea2\u5916=\u5ba2\u5385\u603b\u63a7"},{"content":" phpbrew \u662f\u4e00\u4e2a\u6784\u5efa\u3001\u5b89\u88c5\u591a\u7248\u672c PHP \u5230\u7528\u6237\u6839\u76ee\u5f55\u7684\u5de5\u5177\u3002\n GitHub\uff1ahttps:\/\/github.com\/phpbrew\/phpbrew\nphpbrew \u80fd\u505a\u4ec0\u4e48\uff1f\n \u914d\u7f6e\u9009\u9879\u7b80\u5316\u4e3a\u300cVariants\u300d\uff0c\u65e0\u9700\u62c5\u5fc3\u8def\u5f84\u95ee\u9898\u3002 \u652f\u6301\u4f7f\u7528 PDO\uff0cmysql\uff0csqlite\uff0cdebug \u7b49\u4e0d\u540c\u300cVariants\u300d\u7f16\u8bd1 PHP\u3002 \u9488\u5bf9\u4e0d\u540c\u7248\u672c\uff0c\u5206\u522b\u7f16\u8bd1 apache php \u6a21\u5757\uff0c\u4e92\u4e0d\u51b2\u7a81\u3002 \u65e0\u9700 root \u6743\u9650\u5c06 PHP \u5b89\u88c5\u5230\u7528\u6237\u6839\u76ee\u5f55\u3002 \u96c6\u6210\u81f3 bash \/ zsh shell \u7b49\uff0c\u6613\u4e8e\u5207\u6362\u7248\u672c\u3002 \u652f\u6301\u81ea\u52a8\u7279\u6027\u68c0\u6d4b\u3002 \u6613\u4e8e\u5b89\u88c5\u3001\u542f\u7528 PHP \u6269\u5c55\u3002 \u652f\u6301\u5728\u7cfb\u7edf\u73af\u5883\u4e0b\u5b89\u88c5\u591a\u4e2a PHP\u3002 \u8def\u5f84\u68c0\u6d4b\u9488\u5bf9 HomeBrew \u4ee5\u53ca MacPorts \u8fdb\u884c\u4e86\u4f18\u5316\u3002  \u5b89\u88c5\u9700\u6c42 \u5728\u5f00\u59cb\u4e4b\u524d\uff0c\u8bf7\u5148\u67e5\u770b\uff1aRequirement\uff08\u82f1\u6587\uff09\u3002 \u786e\u4fdd\u5df2\u5b89\u88c5\u4f9d\u8d56\u5305\u7684\u5f00\u53d1\u7248\u672c\u7528\u4e8e\u7f16\u8bd1 PHP\u3002\n\u5b89\u88c5 curl -L -O https:\/\/github.com\/phpbrew\/phpbrew\/raw\/master\/phpbrew chmod +x phpbrew # Move phpbrew to somewhere can be found by your $PATH sudo mv phpbrew \/usr\/local\/bin\/phpbrew \u5feb\u901f\u5165\u95e8 \u6025\u4e0d\u53ef\u5f85\uff1f\u8bf7\u76f4\u63a5\u67e5\u770b\uff1aQuick Start\uff08\u82f1\u6587\uff09\u3002\n\u5f00\u59cb\u4f7f\u7528 \u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u6709\u5145\u8db3\u7684\u65f6\u95f4\u6765\u5b66\u4e60\uff0c\u8fd9\u5c06\u4f1a\u662f\u4e00\u4e2a\u5faa\u5e8f\u6e10\u8fdb\u7684\u6559\u7a0b\u2014\u2014\u6559\u4f60\u5982\u4f55\u914d\u7f6e phpbrew\u3002\n\u521d\u59cb\u8bbe\u7f6e \u9996\u5148\uff0c\u521d\u59cb\u5316 Bash Shell \u811a\u672c\uff1a\nphpbrew init \u63a5\u7740\u5728 .bashrc \u6216 .zshrc \u6587\u4ef6\u589e\u52a0\u5982\u4e0b\u884c\uff1a\n[[ -e ~\/.phpbrew\/bashrc ]] &amp;&amp; source ~\/.phpbrew\/bashrc \u5bf9\u4e8e Fish shell \u7528\u6237\uff0c\u5728 ~\/.config\/fish\/config.fish \u6587\u4ef6\u589e\u52a0\u5982\u4e0b\u884c\uff1a\nsource ~\/.phpbrew\/phpbrew.fish \u82e5\u9700\u8981\u5728\u7cfb\u7edf\u5168\u5c40\uff08\u975e\u7528\u6237\u76ee\u5f55\uff09\u4f7f\u7528 phpbrew\uff0c\u8bf7\u8bbe\u7f6e\u5171\u4eab\u7684 phpbrew \u6839\u76ee\u5f55\uff0c\u4f8b\u5982\uff1a\nmkdir -p \/opt\/phpbrew phpbrew init --root=\/opt\/phpbrew \u5e93\u8def\u5f84\u8bbe\u7f6e \u5176\u6b21\uff0c\u8bf7\u8bbe\u7f6e\u7528\u4e8e\u67e5\u627e\u5e93\u6587\u4ef6\u7684\u9ed8\u8ba4\u524d\u7f00\uff0c\u53ef\u9009\u503c\u6709 macports\uff0chomebrew\uff0cdebian\uff0cubuntu \u6216\u662f\u81ea\u5b9a\u4e49\u8def\u5f84\u3002\n\u5bf9\u4e8e Homebrew \u7528\u6237\uff1a\nphpbrew lookup-prefix homebrew \u5bf9\u4e8e Macports \u7528\u6237\uff1a\nphpbrew lookup-prefix macports \u57fa\u7840\u7528\u6cd5 \u5217\u51fa\u5df2\u77e5 PHP \u7248\u672c\uff1a\nphpbrew known 7.0: 7.0.3, 7.0.2, 7.0.1, 7.0.0 ... 5.6: 5.6.18, 5.6.17, 5.6.16, 5.6.15, 5.6.14, 5.6.13, 5.6.12, 5.6.11 ... 5.5: 5.5.32, 5.5.31, 5.5.30, 5.5.29, 5.5.28, 5.5.27, 5.5.26, 5.5.25 ... 5.4: 5.4.45, 5.4.44, 5.4.43, 5.4.42, 5.4.41, 5.4.40, 5.4.39, 5.4.38 ... 5.3: 5.3.29, 5.3.28 ... \u5217\u51fa\u66f4\u591a\u6b21\u8981\u7248\u672c\uff1a\n$ phpbrew known --more \u5237\u65b0 PHP \u53d1\u5e03\u4fe1\u606f\uff1a\n$ phpbrew update \u5237\u65b0\u65e7\u7248\u672c\uff08\u4f4e\u4e8e 5.4\uff09\uff1a\n \u8bf7\u6ce8\u610f\uff1a\u6211\u4eec\u4e0d\u4fdd\u8bc1\u80fd\u591f\u6b63\u786e\u7f16\u8bd1 PHP \u5b98\u65b9\u505c\u6b62\u7ef4\u62a4\u7684\u7248\u672c\uff0c\u8bf7\u4e0d\u8981\u63d0\u4ea4\u5173\u4e8e\u7f16\u8bd1\u65e7\u7248\u672c\u7684 Issus\uff0c\u6b64\u7c7b Issue \u5c06\u4e0d\u4f1a\u4fee\u590d\u3002\n $ phpbrew update --old \u5217\u51fa\u5df2\u77e5\u7684\u65e7\u7248\u672c\uff08\u4f4e\u4e8e 5.4\uff09\uff1a\n$ phpbrew known --old \u7f16\u8bd1\u5c5e\u4e8e\u4f60\u7684 PHP \u4f7f\u7528\u9ed8\u8ba4\u53c2\u6570\u7f16\u8bd1\u5b89\u88c5 PHP \u975e\u5e38\u7b80\u5355\uff1a\n$ phpbrew install 5.4.0 +default \u8fd9\u91cc\u6211\u4eec\u63a8\u8350\u4f7f\u7528\u5df2\u5305\u542b\u7edd\u5927\u591a\u6570\u516c\u5171\u53c2\u6570\u7684 default\uff08\u9ed8\u8ba4\uff09\u53c2\u6570\u96c6\u5408\u3002\u5982\u679c\u4f60\u9700\u8981\u300c\u6700\u5c0f\u5b89\u88c5\u300d\uff0c\u5220\u6389default\u6267\u884c\u5373\u53ef\u3002\n\u4f60\u53ef\u4ee5\u4f7f\u7528-j\u6216--jobs\u9009\u9879\u542f\u7528\u5e76\u884c\u7f16\u8bd1\uff0c\u4f8b\u5982\uff1a\n$ phpbrew install -j $(nproc) 5.4.0 +default \u7f16\u8bd1\u5b8c\u6210\u540e\u6267\u884c\u6d4b\u8bd5\u7528\u4f8b\uff1a\n$ phpbrew install --test 5.4.0 \u6d4b\u8bd5\u73af\u5883\uff0c\u4e14\u5305\u542b\u8c03\u8bd5\u4fe1\u606f\uff1a\n$ phpbrew -d install --test 5.4.0 \u5b89\u88c5\u65e7\u7248\u672c\uff08\u4f4e\u4e8e 5.3\uff09\uff1a\n$ phpbrew install --old 5.2.13 \u5b89\u88c5\u7ed9\u5b9a\u4e3b\u8981\u7248\u672c\u7684\u6700\u65b0\u6b21\u8981\u7248\u672c\uff1a\n$ phpbrew install 5.6 \u5b89\u88c5\u9884\u89c8\u7248\u672c\uff1a\n$ phpbrew install 7.2.0alpha1 $ phpbrew install 7.2.0beta2 $ phpbrew install 7.2.0RC3 \u901a\u8fc7\u6307\u5b9a\u7684 GitHub tag \u6216 branch \u5b89\u88c5\uff1a\n$ phpbrew install github:php\/php-src@PHP-7.2 as php-7.2.0-dev \u5b89\u88c5\u4e0b\u4e00\u4e2a\uff08\u975e\u7a33\u5b9a\uff09\u7248\u672c\uff1a\n$ phpbrew install next as php-7.3.0-dev \u6e05\u9664\u7f16\u8bd1\u76ee\u5f55 $ phpbrew clean php-5.4.0 Variants PHPBrew \u5df2\u7ecf\u5c06\u914d\u7f6e\u9009\u9879\u6574\u7406\u3001\u5408\u5e76\u4e3a\u300cVariants\u300d\uff0c\u4f60\u53ea\u9700\u7b80\u5355\u5730\u6307\u5b9a\u67d0\u4e2a Variant \u5373\u53ef\uff0cphpbrew \u4f1a\u81ea\u52a8\u5728\u914d\u7f6e\u8fc7\u7a0b\u4e2d\u68c0\u6d4b\u5f15\u7528\u76ee\u5f55\u3001\u7f16\u8bd1\u9009\u9879\u7b49\u3002\nPHPBrew \u63d0\u4f9b\u9ed8\u8ba4\u7684 Variant \uff0c\u4ee5\u53ca\u4e00\u4e9b\u865a\u62df Variants\u3002 \u300cDefault Variant\u300d\u5305\u542b\u7edd\u5927\u591a\u6570\u516c\u5171 Variants\uff1b \u300cVirtual Variants\u300d\u53ef\u5305\u542b\u591a\u4e2a Variants\uff0c\u4f7f\u7528\u4e00\u4e2a\u865a\u62df Variant \u5373\u53ef\u4e00\u6b21\u6027\u542f\u7528\u591a\u4e2a Variants\u3002\n\u53ea\u9700\u6267\u884cvariants\u5b50\u547d\u4ee4\uff0c\u5373\u53ef\u5217\u51fa\u5b83\u4eec\uff1a\n$ phpbrew variants Variants: all, apxs2, bcmath, bz2, calendar, cgi, cli, ctype, curl, dba, debug, dom, dtrace, editline, embed, exif, fileinfo, filter, fpm, ftp, gcov, gd, gettext, gmp, hash, iconv, icu, imap, inifile, inline, intl, ipc, ipv6, json, kerberos, libgcc, mbregex, mbstring, mcrypt, mhash, mysql, opcache, openssl, pcntl, pcre, pdo, pgsql, phar, phpdbg, posix, readline, session, soap, sockets, sqlite, static, tidy, tokenizer, wddx, xml, xml_all, xmlrpc, zip, zlib, zts Virtual variants: dbs: sqlite, mysql, pgsql, pdo mb: mbstring, mbregex neutral: small: bz2, cli, dom, filter, ipc, json, mbregex, mbstring, pcre, phar, posix, readline, xml, curl, openssl default: bcmath, bz2, calendar, cli, ctype, dom, fileinfo, filter, ipc, json, mbregex, mbstring, mhash, mcrypt, pcntl, pcre, pdo, phar, posix, readline, sockets, tokenizer, xml, curl, openssl, zip everything: dba, ipv6, dom, calendar, wddx, static, inifile, inline, cli, ftp, filter, gcov, zts, json, hash, exif, mbstring, mbregex, libgcc, pdo, posix, embed, sockets, debug, phpdbg, zip, bcmath, fileinfo, ctype, cgi, soap, pcntl, phar, session, tokenizer, opcache, imap, tidy, kerberos, xmlrpc, fpm, dtrace, pcre, mhash, mcrypt, zlib, curl, readline, editline, gd, intl, icu, openssl, mysql, sqlite, pgsql, xml, xml_all, gettext, iconv, bz2, ipc, gmp Using variants to build PHP: phpbrew install php-5.3.10 +default phpbrew install php-5.3.10 +mysql +pdo phpbrew install php-5.3.10 +mysql +pdo +apxs2 phpbrew install php-5.3.10 +mysql +pdo +apxs2=\/usr\/bin\/apxs2 \u5728 Variant \u524d\u6dfb\u52a0+\u524d\u7f00\uff0c\u4ee3\u8868\u542f\u7528\u6b64 Variant\uff0c\u4f8b\u5982\uff1a\n+mysql  \u5728 Variant \u524d\u6dfb\u52a0-\u524d\u7f00\uff0c\u4ee3\u8868\u7981\u7528\u6b64 Variant\uff0c\u4f8b\u5982\uff1a\n-mysql  \u4e3e\u4e2a\u4f8b\u5b50\uff0c\u5047\u8bbe\u4f60\u4f7f\u7528\u9ed8\u8ba4 Variant\uff0c\u5e76\u4e14\u9700\u8981\u542f\u7528\u6570\u636e\u5e93\u652f\u6301\uff08mysql\uff0csqlite\uff0cpostgresql\uff09\u7f16\u8bd1 PHP\uff0c\u53ea\u9700\u6267\u884c\uff1a\n$ phpbrew install 5.4.5 +default+dbs \u4e5f\u53ef\u4ee5\uff1a\n$ phpbrew install 5.3.10 +mysql+sqlite+cgi $ phpbrew install 5.3.10 +mysql+debug+pgsql +apxs2 $ phpbrew install 5.3.10 +pdo +mysql +pgsql +apxs2=\/usr\/bin\/apxs2 \u5c06 pgsql (PostgreSQL) \u6269\u5c55\u7f16\u8bd1\u8fdb PHP\uff1a\n$ phpbrew install 5.4.1 +pgsql+pdo \u82e5\u4f60\u7684 Mac \u4e0a\u5df2\u7ecf\u5b89\u88c5 postgresql\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u7279\u5b9a\u76ee\u5f55\u7f16\u8bd1 pgsql \u6269\u5c55\uff1a\n$ phpbrew install 5.4.1 +pdo+pgsql=\/opt\/local\/lib\/postgresql91\/bin pgsql \u7684\u8def\u5f84\u5373\u4e3apg_config\u6240\u5728\u76ee\u5f55\uff0c\u4f60\u53ef\u4ee5\u5728\/opt\/local\/lib\/postgresql91\/bin\u627e\u5230\u5b83\u3002\n\u53e6\u5916\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u540d\u4e3aneutral\u7684 Variant \u6765\u7eaf\u51c0\u7f16\u8bd1 PHP\uff1a\n$ phpbrew install 5.4.1 +neutral neutral\u610f\u5473\u7740 phpbrew \u4e0d\u4f1a\u589e\u52a0\u5305\u62ec--disable-all\u5728\u5185\u7684\u4efb\u4f55\u989d\u5916\u7f16\u8bd1\u53c2\u6570\uff0c\u4f46\u90e8\u5206\u7528\u4e8e\u5b89\u88c5pear\u7684\u53c2\u6570\uff08\u4f8b\u5982--enable-libxml\uff09\u4f9d\u65e7\u4f1a\u88ab\u6dfb\u52a0\u3002\n\u66f4\u591a\u7ec6\u8282\uff0c\u8bf7\u79fb\u6b65\uff1aPHPBrew Cookbook\uff08\u82f1\u6587\uff09\u3002\n\u62d3\u5c55\u914d\u7f6e\u9009\u9879 \u5982\u679c\u60f3\u8981\u4f20\u9012\u66f4\u591a\u62d3\u5c55\u914d\u7f6e\u53d8\u91cf\uff0c\u4f60\u53ef\u4ee5\u8fd9\u4e48\u505a\uff1a\n$ phpbrew install 5.3.10 +mysql +sqlite -- \\  --enable-ftp --apxs2=\/opt\/local\/apache2\/bin\/apxs \u5207\u6362 PHP \u7248\u672c \u4e34\u65f6\u5207\u6362 PHP \u7248\u672c\uff1a\n$ phpbrew use 5.4.22 \u5207\u6362\u9ed8\u8ba4 PHP \u7248\u672c\uff1a\n$ phpbrew switch 5.4.18 \u5173\u95ed phpbrew\uff1a\n$ phpbrew off \u82e5\u9700\u8981\u542f\u7528 Apache PHP \u6a21\u5757\uff0c\u8bf7\u6ce8\u91ca\u6216\u79fb\u9664\u4ee5\u4e0b\u8bbe\u7f6e\u9879\uff1a\n$ sudo vim \/etc\/httpd\/conf\/httpd.conf # LoadModule php5_module \/usr\/lib\/httpd\/modules\/libphp5.3.21.so # LoadModule php5_module \/usr\/lib\/httpd\/modules\/libphp5.3.20.so \u6269\u5c55\u5b89\u88c5\u5668 \u8bf7\u67e5\u770b\uff1aExtension Installer\uff08\u82f1\u6587\uff09\u3002\n\u914d\u7f6e php.ini \u914d\u7f6e\u5f53\u524d PHP \u7248\u672c\u7684 php.ini \u6587\u4ef6\uff0c\u53ea\u9700\u6267\u884c\u5982\u4e0b\u547d\u4ee4\u5373\u53ef\uff1a\n$ phpbrew config \u5982\u9700\u5207\u6362\u7f16\u8f91\u5668\uff0c\u53ef\u6267\u884c\u5982\u4e0b\u547d\u4ee4\u6307\u5b9a EDITOR \u73af\u5883\u53d8\u91cf\uff1a\nexport EDITOR=vim phpbrew config \u5347\u7ea7 phpbrew \u6267\u884c self-update \u5373\u53ef\u4ece GitHub \u7684 master \u5206\u652f\u5b89\u88c5 phpbrew \u6700\u65b0\u7248\u672c\u3002\n$ phpbrew self-update \u5df2\u5b89\u88c5\u7684 PHP \u5217\u51fa\u5df2\u5b89\u88c5\u7684 PHP\uff1a\n$ phpbrew list \u4f60\u53ef\u4ee5\u5728 ~\/.phpbrew\/php \u76ee\u5f55\u627e\u5230\u5df2\u5b89\u88c5\u7684 PHP\u3002\u4f8b\u5982\uff0c5.4.20 \u7248\u672c\u4f4d\u4e8e\uff1a\n~\/.phpbrew\/php\/5.4.20\/bin\/php  \u4f60\u53ef\u4ee5\u624b\u52a8\u4fee\u6539\u5176 php.ini\uff1a\n~\/.phpbrew\/php\/5.4.20\/etc\/php.ini  \u800c PHP \u6269\u5c55\u7684\u914d\u7f6e\u6587\u4ef6\u4f4d\u4e8e\uff1a\n~\/.phpbrew\/php\/5.4.20\/var\/db ~\/.phpbrew\/php\/5.4.20\/var\/db\/xdebug.ini ~\/.phpbrew\/php\/5.4.20\/var\/db\/apc.ini ~\/.phpbrew\/php\/5.4.20\/var\/db\/memcache.ini \u7b49\u7b49...  \u4e00\u952e\u5207\u6362\u76ee\u5f55 \u5207\u6362\u81f3 PHP \u7f16\u8bd1\u76ee\u5f55\uff1a\n$ phpbrew build-dir \u5207\u6362\u81f3 PHP dist \u76ee\u5f55\uff1a\n$ phpbrew dist-dir \u5207\u6362\u81f3 PHP etc \u76ee\u5f55\uff1a\n$ phpbrew etc-dir \u5207\u6362\u81f3 PHP var \u76ee\u5f55\uff1a\n$ phpbrew var-dir PHP FPM phpbrew \u5185\u7f6e\u4e00\u4e9b\u6709\u7528\u7684\u547d\u4ee4\u7528\u4e8e\u7ba1\u7406 php-fpm\u3002\u4f7f\u7528\u5b83\u4eec\u4e4b\u524d\uff0c\u8bf7\u786e\u8ba4\u5728 PHP \u7f16\u8bd1\u65f6\u542f\u7528\u4e86 +fpm\u3002\n\u542f\u52a8 php-fpm\uff1a\n$ phpbrew fpm start \u505c\u6b62 php-fpm\uff1a\n$ phpbrew fpm stop \u5217\u51fa php-fpm \u6a21\u5757\uff1a\nphpbrew fpm module \u6d4b\u8bd5 php-fpm \u914d\u7f6e\uff1a\nphpbrew fpm test \u7f16\u8f91 php-fpm \u914d\u7f6e\uff1a\nphpbrew fpm config  \u5df2\u5b89\u88c5\u7684 php-fpm \u4f4d\u4e8e ~\/.phpbrew\/php\/php-*\/sbin \u76ee\u5f55\u3002\n\u5bf9\u5e94\u7684 php-fpm.conf \u6587\u4ef6\u4f4d\u4e8e ~\/.phpbrew\/php\/php-*\/etc\/php-fpm.conf.default \u76ee\u5f55\u3002\n\u4f60\u53ef\u4ee5\u628a\u9ed8\u8ba4\u914d\u7f6e\u590d\u5236\u5230\u81ea\u5b9a\u4e49\u8def\u5f84\u518d\u4f7f\u7528\uff0c\u4f8b\u5982\uff1a\ncp -v ~\/.phpbrew\/php\/php-*\/etc\/php-fpm.conf.default ~\/.phpbrew\/php\/php-*\/etc\/php-fpm.conf php-fpm --php-ini {php config file} --fpm-config {fpm config file}   \u5b89\u88c5\u62d3\u5c55\u5e94\u7528 phpbrew \u5185\u7f6e\u4e86\u7528\u6765\u83b7\u53d6\u90e8\u5206 PHP \u5e94\u7528\u7684 app \u547d\u4ee4\u3002\n\u5b89\u88c5 Composer $ phpbrew app get composer \u5b89\u88c5 PHPUnit phpbrew app get phpunit \u542f\u7528\u7248\u672c\u4fe1\u606f Prompt \u4f7f\u7528&quot;PHPBREW_SET_PROMPT=1&quot;\u53d8\u91cf\u53ef\u5c06 PHP \u7248\u672c\u4fe1\u606f\u52a0\u5165 Shell Prompt\u3002\n\u6b64\u53d8\u91cf\u9ed8\u8ba4\u503c\u4e3a&quot;PHPBREW_SET_PROMPT=0&quot;\uff08\u5373\u7981\u7528\uff09\uff0c\u5c06\u5982\u4e0b\u884c\u52a0\u5165~\/.bashrc\u6587\u4ef6\uff0c\u786e\u4fdd\u5176\u5728source ~\/.phpbrew\/bashrc\u4e4b\u524d\uff0c\u5373\u53ef\u542f\u7528\u6b64\u529f\u80fd\uff1a\nexport PHPBREW_SET_PROMPT=1 \u4f7f\u7528.phpbrew\/bashrc\u5185\u5b9a\u4e49\u7684phpbrew_current_php_version\u51fd\u6570\uff0c\u53ef\u5c06\u7248\u672c\u4fe1\u606f\u5d4c\u5165\u5230 Shell Prompt\u3002\u4f60\u53ef\u4ee5\u5c06\u7248\u672c\u4fe1\u606f\u8bbe\u7f6e\u5230 PS1 \u53d8\u91cf\u5185\uff0c\u4f8b\u5982\uff1a\nPS1=&#34; \\$(phpbrew_current_php_version) \\$ &#34; \u5df2\u77e5\u95ee\u9898   \u5bf9\u4e8e PHP-5.3+ \u7248\u672c\uff0c&ldquo;Building intl 64-bit fails on OS X&rdquo; https:\/\/bugs.php.net\/bug.php?id=48795\n  \u5c06 GD \u6269\u5c55\u7f16\u8bd1\u8fdb PHP\uff0c\u4f60\u9700\u8981\u6307\u5b9a libpng \u76ee\u5f55\u3001libjpeg \u76ee\u5f55\uff0c\u4f8b\u5982\uff1a\n$ phpbrew install php-5.4.10 +default +mysql +intl +gettext +apxs2=\/usr\/bin\/apxs2\n&ndash; &ndash;with-libdir=lib\/x86_64-linux-gnu\n&ndash;with-gd=shared\n&ndash;enable-gd-natf\n&ndash;with-jpeg-dir=\/usr\n&ndash;with-png-dir=\/usr\n  \u6545\u969c\u6392\u67e5 \u8bf7\u79fb\u6b65\uff1aTroubleShooting\uff08\u82f1\u6587\uff09\u3002\n\u5e38\u89c1\u95ee\u7b54 Q: \u5982\u4f55\u4f7f\u7528\u4e0d\u540c\u7684\u53c2\u6570\u7f16\u8bd1\u76f8\u540c PHP \u7248\u672c\uff1f\nA: \u622a\u81f3\u76ee\u524d\uff0c\u4f60\u53ef\u4ee5\u5b89\u88c5 php-5.x.x \u5e76\u91cd\u547d\u540d\u5176\u76ee\u5f55 \/Users\/phpbrew\/.phpbrew\/php\/php-5.x.x\uff08\u4f8b\u5982\uff1aphp-5.x.x-super\uff09\uff0c\u5e76\u5b89\u88c5\u53e6\u4e00\u4e2a php5.x.x\u3002\n\u53c2\u4e0e\u8d21\u732e \u8bf7\u79fb\u6b65\uff1aContribution\uff08\u82f1\u6587\uff09\u3002\n\u6587\u6863 \u8bf7\u79fb\u6b65\uff1aWiki\uff08\u82f1\u6587\uff09\u3002\n\u4f5c\u8005  Yo-An Lin (c9s)  M\u00e1rcio Almad   \u6388\u6743 \u8bf7\u67e5\u770b\uff1aLICENSE \u6587\u4ef6\u3002\n\u7ffb\u8bd1  @wi1dcard @\u8766\u7c73 Waiting for you&hellip;  \u5e0c\u671b\u5927\u5bb6\u5171\u540c\u53c2\u4e0e\u5230\u7ffb\u8bd1\u5de5\u4f5c\u4e2d\uff1b\u5982\u6709\u4e0d\u5f53\uff0c\u70e6\u8bf7\u6307\u6b63\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/phpbrew-documention\/","summary":"phpbrew \u662f\u4e00\u4e2a\u6784\u5efa\u3001\u5b89\u88c5\u591a\u7248\u672c PHP \u5230\u7528\u6237\u6839\u76ee\u5f55\u7684\u5de5\u5177\u3002\n GitHub\uff1ahttps:\/\/github.com\/phpbrew\/phpbrew\nphpbrew \u80fd\u505a\u4ec0\u4e48\uff1f\n \u914d\u7f6e\u9009\u9879\u7b80\u5316\u4e3a\u300cVariants\u300d\uff0c\u65e0\u9700\u62c5\u5fc3\u8def\u5f84\u95ee\u9898\u3002 \u652f\u6301\u4f7f\u7528 PDO\uff0cmysql\uff0csqlite\uff0cdebug \u7b49\u4e0d\u540c\u300cVariants\u300d\u7f16\u8bd1 PHP\u3002 \u9488\u5bf9\u4e0d\u540c\u7248\u672c\uff0c\u5206\u522b\u7f16\u8bd1 apache php \u6a21\u5757\uff0c\u4e92\u4e0d\u51b2\u7a81\u3002 \u65e0\u9700 root \u6743\u9650\u5c06 PHP \u5b89\u88c5\u5230\u7528\u6237\u6839\u76ee\u5f55\u3002 \u96c6\u6210\u81f3 bash \/ zsh shell \u7b49\uff0c\u6613\u4e8e\u5207\u6362\u7248\u672c\u3002 \u652f\u6301\u81ea\u52a8\u7279\u6027\u68c0\u6d4b\u3002 \u6613\u4e8e\u5b89\u88c5\u3001\u542f\u7528 PHP \u6269\u5c55\u3002 \u652f\u6301\u5728\u7cfb\u7edf\u73af\u5883\u4e0b\u5b89\u88c5\u591a\u4e2a PHP\u3002 \u8def\u5f84\u68c0\u6d4b\u9488\u5bf9 HomeBrew \u4ee5\u53ca MacPorts \u8fdb\u884c\u4e86\u4f18\u5316\u3002  \u5b89\u88c5\u9700\u6c42 \u5728\u5f00\u59cb\u4e4b\u524d\uff0c\u8bf7\u5148\u67e5\u770b\uff1aRequirement\uff08\u82f1\u6587\uff09\u3002 \u786e\u4fdd\u5df2\u5b89\u88c5\u4f9d\u8d56\u5305\u7684\u5f00\u53d1\u7248\u672c\u7528\u4e8e\u7f16\u8bd1 PHP\u3002","title":"PHPBrew - \u591a\u7248\u672c PHP \u5171\u5b58\u5f00\u53d1\u795e\u5668"},{"content":" \u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u91c7\u7528 TCP Socket \u4e0e\u667a\u80fd\u786c\u4ef6\u8fdb\u884c\u901a\u4fe1\u3002\u5916\u7f51\u73af\u5883\u4e2d\uff0c\u6709\u65e0\u6570\u79cd\u89e3\u51b3\u65b9\u6848\uff1aSwoole\uff08PHP\uff09\uff0cNode.js\uff0cSuperSocket\uff08.NET\uff09\u2026\u2026 \u800c\u5728\u653f\u4f01\u4e8b\u4e1a\u5355\u4f4d\u7684\u5185\u7f51\u73af\u5883\uff0c\u4e8b\u60c5\u6216\u8bb8\u5c31\u4e0d\u90a3\u4e48\u597d\u529e\u4e86\u3002\n 0x01 \u76ee\u7684  \u63a5\u6536\u6765\u81ea\u786c\u4ef6\u7684\u6570\u636e\uff0c\u5e76\u5728 Web \u7aef\u5c55\u793a\u3002 \u901a\u8fc7 Web \u7aef\u64cd\u4f5c\uff0c\u5c06\u6307\u4ee4\u4e0b\u53d1\u81f3\u786c\u4ef6\u3002  0x02 \u9650\u5236  \u6d4f\u89c8\u5668\u9700\u8981\u652f\u6301 IE \u7b49\u8001\u7248\u672c\u6d4f\u89c8\u5668\u3002 \u670d\u52a1\u7aef\u9700\u8981\u652f\u6301 Windows Server \u865a\u62df\u673a\uff08\u6700\u4f4e\u7248\u672c 2008\uff09\u3002 \u7eaf\u5185\u7f51\u73af\u5883\uff0c\u65e0\u6cd5\u8bbf\u95ee\u5916\u7f51\u6e90\uff0c\u65e0\u6cd5\u4f7f\u7528\u5404\u7c7b\u5305\u7ba1\u7406\u5668\uff08\u5176\u5b9e\u53ef\u4ee5\u81ea\u5df1\u642d\u5efa\u5185\u7f51\u6e90\uff0c\u4f46\u8fc7\u4e8e\u590d\u6742\uff0c\u4eba\u529b\u6210\u672c\u592a\u9ad8\uff09\u3002  0x03 \u601d\u8def \u76ee\u524d\u516c\u53f8 Web \u540e\u7aef\u8bed\u8a00\u5747\u4e3a PHP\uff0c\u6240\u4ee5\u4ee5\u4e0b\u601d\u8def\u5168\u90e8\u56f4\u7ed5 PHP \u5f00\u5c55\u3002\nPlan A-1 \u65e2\u7136\u56f4\u7ed5 PHP\uff0c\u9996\u5148\u6211\u6240\u60f3\u5230\u7684\u5c31\u662f\u8fd9\u79cd\u65b9\u6848\uff1a\nAjax\/Axios + PHP + Swoole + Hardware\n \u524d\u7aef\u4e4b\u6240\u4ee5\u4e0d\u91c7\u7528 WebSocket\uff0c\u6d4f\u89c8\u5668\u517c\u5bb9\u6027\u3002\n \u8fd9\u4e5f\u662f\u6211\u524d\u51e0\u5929\u7684\u6280\u672f\u535a\u5ba2\u300cLaravel + Swoole \u5b9e\u73b0 TCP\/UDP Socket \u670d\u52a1\u7aef\u300d\u6240\u8bbe\u60f3\u7684\uff0c\u4f46\u5f88\u5feb\u8fd9\u79cd\u65b9\u6848\u88ab\u6bd9\u4e86\uff0c\u539f\u56e0\u5f88\u7b80\u5355\uff1a\n Swoole \u4e0d\u652f\u6301 Windows\u3002  Plan A-2 \u90a3\u4e48\u662f\u5426\u6709\u529e\u6cd5\u5728 Windows \u4e0b\u8fd0\u884c Swoole\uff1f\n Cygwin\uff1f\u6bd9\u4e86\uff0c\u5185\u7f51\u4e0d\u80fd\u4e0b\u8f7d\u5305\u3002 Hyper-V \u865a\u62df\u673a\u8dd1 Linux\uff1f\u6bd9\u4e86\uff0c\u5d4c\u5957\u865a\u62df\u5316 Windows Server 2016 \u624d\u652f\u6301\u3002 VMware\uff1fVirtual Box\uff1f\u6bd9\u4e86\uff0c\u4e14\u4e0d\u8bf4\u7269\u7406\u673a\u7684\u865a\u62df\u5c42\u652f\u6301\u4e0d\u652f\u6301\u5d4c\u5957\u865a\u62df\u5316\uff08Nested\uff09\uff0c\u5c31\u662f\u652f\u6301\uff0c\u6307\u4e0d\u5b9a\u5361\u6210\u4ec0\u4e48\u6837\u3002 Docker\uff1f\u4e0d\u7528\u60f3\uff0c\u6bd9\u4e86\uff0cDocker for Windows \u57fa\u4e8e Hyper-V\u3002  Plan B-1 \u6bd9\u4e86 Swoole\uff0c\u8fd8\u6709 Workerman \u554a\u3002\n\u4e8e\u662f\u770b\u4e86\u4e0b walkor\/workerman-for-win\uff0c\u51c9\u51c9\u3002\n\u76f8\u6bd4\u4e8e Workerman Linux \u7248\u672c\u51e0\u5343\u4e2a Star\uff0c\u7b80\u76f4\u5c2c\u554a\u3002\u518d\u52a0\u4e0a README \u6807\u660e\u7684\uff1a\u300c\u6b64\u7248\u672c\u53ef\u7528\u4e8e windows \u4e0b\u5f00\u53d1\u4f7f\u7528\uff0c\u4e0d\u5efa\u8bae\u7528\u5728\u751f\u4ea7\u73af\u5883\u300d\u3002\u6700\u540e\uff0c\u770b\u4e86\u770b\u6587\u6863\uff0cWin \u7248\u672c\u5c11\u4e86\u4e9b\u5bf9\u4e8e\u63d0\u9ad8\u6027\u80fd\u5341\u5206\u6709\u76ca\u7684\u91cd\u8981\u7279\u6027\u3002\n\u6bd9\u4e86\u3002\nPlan B-2 \u4e0d\u6b7b\u5fc3\uff0cGitHub \u4e0a\u627e\u627e\u6709\u6ca1\u6709\u5c0f\u4f17\u53c8\u6210\u719f\u7684 PHP Socket \u670d\u52a1\u7aef\u3002\n reactphp\/socket hoaproject\/Socket  \u524d\u8005\u5185\u90e8\u672a\u5904\u7406 TCP \u7c98\u5305 \u95ee\u9898\uff0c\u624b\u52a8\u5904\u7406\u5bf9\u4e8e PHP \u7ec4\u6765\u8bf4\u96be\u5ea6\u76f8\u5f53\u2026\u2026\u5de8\u5927\u3002\n\u540e\u8005\u6587\u6863\u4e0d\u5168\uff0c\u975e\u4e8b\u4ef6\u9a71\u52a8\uff0c\u5c45\u7136\u8fd8\u662f\u5355\u8fdb\u7a0b\u3001\u5355\u7ebf\u7a0b\u7684 while \u5faa\u73af\u3002\n\u6bd9\u4e86\u3002\nPlan C \u4e8e\u662f\u51b3\u5b9a\uff0c\u4e0d\u5f97\u4e0d\u6362\u4e00\u95e8\u8bed\u8a00\u5904\u7406\u8fd9\u4e2a\u95ee\u9898\u3002\u300c\u8fd9\u95e8\u8bed\u8a00\u300d\u5fc5\u987b\u5177\u6709\uff1a\u6613\u90e8\u7f72\u3001\u7a33\u5b9a\u3001\u517c\u5bb9 Windows \u7684\u7279\u6027\u3002\n\u5c3d\u7ba1\u6211\u9996\u5148\u60f3\u5230\u7684\u662f\u5fae\u8f6f\u7684\u4eb2\u513f\u5b50 .NET\uff0c\u4f46\u53e6\u4e00\u95e8\u8bed\u8a00\u4e5f\u6d6e\u73b0\u5728\u6211\u7684\u8111\u6d77\u91cc\uff1aNode.js\u3002\nNode.js \u672c\u8eab\u6240\u5177\u6709\u7684\u4e8b\u4ef6\u9a71\u52a8\u3001\u975e\u963b\u585e IO \u7b49\u7279\u6027\u5341\u5206\u9002\u5408\u7528\u6765\u5f00\u53d1 Socket \u670d\u52a1\u7aef\uff1b\u8fd9\u4e00\u70b9\u5728\u5404\u7c7b\u793e\u533a\u4e5f\u5f97\u5230\u5370\u8bc1\uff0c\u4f7f\u7528 Node \u5f00\u53d1\u7684 WebSocket\u3001Socket \u670d\u52a1\u7aef\u5c42\u51fa\u4e0d\u7a77\uff0c\u4e14\u5341\u5206\u6d3b\u8dc3\uff1b\u800c\u5fae\u8f6f\u7684\u652f\u6301\u4e5f\u4e0d\u5dee\uff0cVS Code \u5c31\u662f\u57fa\u4e8e Node \u5f00\u53d1\u3002\n\u4f46\u75db\u70b9\u4e5f\u6709\uff0c\u4f8b\u5982\uff1a\u5168\u662f\u56de\u8c03\uff0c\u968f\u7740\u9879\u76ee\u89c4\u6a21\u589e\u957f\uff0c\u56de\u8c03\u8d8a\u6765\u8d8a\u591a\uff0c\u53c2\u6570\u7c7b\u578b\u4e0d\u660e\u786e\uff0c\u5f02\u5e38\u5904\u7406\u56f0\u96be\uff0c\u4e07\u4e00\u54ea\u91cc\u6ca1\u5199\u597d\u9020\u6210\u9690\u85cf BUG\uff0c\u52a8\u4e0d\u52a8\u5c31\u5d29\u6e83\uff0c\u9ebb\u70e6\u53ef\u5c31\u5927\u4e86\u3002\u4f55\u51b5\u516c\u53f8\u76ee\u524d\u8fd8\u6ca1\u6709\u4e13\u4e1a\u73a9 Node \u7684\u7a0b\u5e8f\u5458\u3002\n \u4e2a\u4eba\u8ba4\u4e3a\uff0cNode.js \u81ea\u5df1\u73a9\u73a9\u5165\u95e8\u7b80\u5355\uff0c\u51e0\u884c\u4ee3\u7801\u5c31\u80fd\u4e0a\u624b\u8fd0\u884c\uff0c\u4f46\u60f3\u8981\u5728\u751f\u4ea7\u73af\u5883\u4e0b\u73a9\u8f6c Node\uff1a\u4e00\u65b9\u9762\u9700\u8981\u5f88\u5f3a\u7684\u7f16\u7a0b\u601d\u7ef4\u529f\u5e95\uff0c\u4e0d\u7136\u5f88\u96be\u7406\u89e3\u8fd9\u79cd\u5b8c\u5168\u975e\u963b\u585e\u7684\u6a21\u5f0f\uff1b\u53e6\u4e00\u65b9\u9762\u9700\u8981\u5bf9 Node \u6587\u6863\u8fdb\u884c\u901a\u8bfb\uff0c\u5177\u6709\u4e00\u5b9a\u4e86\u89e3\u3001\u7ecf\u9a8c\uff0c\u5426\u5219\u4e07\u4e00\u67d0\u4e2a\u53d8\u91cf\u7c7b\u578b\u641e\u9519\u629b\u51fa\u5f02\u5e38\uff0c\u6216\u662f Buffer \u4f7f\u7528\u4e0d\u5f53\u5bfc\u81f4\u5185\u5b58\u6cc4\u9732\uff0c\u90a3\u90fd\u662f\u9690\u6027\u4e14\u81f4\u547d\u7684\u3002\n \u5fcd\u75db\u5272\u7231\uff01\u6bd9\u4e86\u3002\nPlan D \u6700\u540e\u4e00\u4e2a\u65b9\u6848\uff0c.NET\u3002\u5927\u81f4\u601d\u8def\u662f\u8fd9\u6837\u7684\u3002\nAjax\/Axios + PHP + .NET + Hardware\n .NET \u65b9\u9762\u91c7\u7528\u6210\u719f\u7684 TCP\/UDP \u670d\u52a1\u7aef\u7ec4\u4ef6 \u2014\u2014 SuperSocket PHP \u4e0e .NET \u76f8\u4e92\u901a\u4fe1\uff0c\u53ef\u4ee5\u91c7\u7528 Redis \u6d88\u606f\u961f\u5217\uff0cMySQL \u4e2d\u8f6c\u7b49\u65b9\u6848\uff1b\u4e5f\u53ef\u4ee5\u5c06 PHP \u4f5c\u4e3a TCP Client \u5bf9 SuperSocket \u53d1\u9001\u6570\u636e\uff0c\u5f53 SuperSocket \u63a5\u6536\u5230\u786c\u4ef6\u6570\u636e\u65f6\uff0c\u8c03\u7528 PHP \u7f16\u5199\u7684 HTTP API \u5373\u53ef\u3002  \u8fd9\u662f\u76ee\u524d\u6211\u80fd\u60f3\u5230\u7684\uff0c\u7ed3\u5408\u73b0\u5b9e\u60c5\u51b5\uff0c\u6700\u8282\u7701\u4eba\u529b\u7269\u529b\u6210\u672c\uff0c\u4e14\u76f8\u5bf9\u7a33\u5b9a\u3001\u7b80\u6613\u7684\u89e3\u51b3\u65b9\u6848\u3002\u90e8\u7f72\u65f6\u53ea\u9700\u8981\uff1a\n \u8fd0\u884c WNMP\uff0c\u8dd1 PHP \u4ee3\u7801\u3002 \u5b89\u88c5 .NET Framework\uff0c\u8dd1 .NET \u670d\u52a1\u7aef\u3002  \u5373\u53ef\u3002\n0x04 \u611f\u60f3 \u5185\u7f51\uff0c\u5751\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/controlling-smart-device-on-web\/","summary":"\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u91c7\u7528 TCP Socket \u4e0e\u667a\u80fd\u786c\u4ef6\u8fdb\u884c\u901a\u4fe1\u3002\u5916\u7f51\u73af\u5883\u4e2d\uff0c\u6709\u65e0\u6570\u79cd\u89e3\u51b3\u65b9\u6848\uff1aSwoole\uff08PHP\uff09\uff0cNode.js\uff0cSuperSocket\uff08.NET\uff09\u2026\u2026 \u800c\u5728\u653f\u4f01\u4e8b\u4e1a\u5355\u4f4d\u7684\u5185\u7f51\u73af\u5883\uff0c\u4e8b\u60c5\u6216\u8bb8\u5c31\u4e0d\u90a3\u4e48\u597d\u529e\u4e86\u3002\n 0x01 \u76ee\u7684  \u63a5\u6536\u6765\u81ea\u786c\u4ef6\u7684\u6570\u636e\uff0c\u5e76\u5728 Web \u7aef\u5c55\u793a\u3002 \u901a\u8fc7 Web \u7aef\u64cd\u4f5c\uff0c\u5c06\u6307\u4ee4\u4e0b\u53d1\u81f3\u786c\u4ef6\u3002  0x02 \u9650\u5236  \u6d4f\u89c8\u5668\u9700\u8981\u652f\u6301 IE \u7b49\u8001\u7248\u672c\u6d4f\u89c8\u5668\u3002 \u670d\u52a1\u7aef\u9700\u8981\u652f\u6301 Windows Server \u865a\u62df\u673a\uff08\u6700\u4f4e\u7248\u672c 2008\uff09\u3002 \u7eaf\u5185\u7f51\u73af\u5883\uff0c\u65e0\u6cd5\u8bbf\u95ee\u5916\u7f51\u6e90\uff0c\u65e0\u6cd5\u4f7f\u7528\u5404\u7c7b\u5305\u7ba1\u7406\u5668\uff08\u5176\u5b9e\u53ef\u4ee5\u81ea\u5df1\u642d\u5efa\u5185\u7f51\u6e90\uff0c\u4f46\u8fc7\u4e8e\u590d\u6742\uff0c\u4eba\u529b\u6210\u672c\u592a\u9ad8\uff09\u3002  0x03 \u601d\u8def \u76ee\u524d\u516c\u53f8 Web \u540e\u7aef\u8bed\u8a00\u5747\u4e3a PHP\uff0c\u6240\u4ee5\u4ee5\u4e0b\u601d\u8def\u5168\u90e8\u56f4\u7ed5 PHP \u5f00\u5c55\u3002","title":"\u7ea0\u7ed3\uff01\u7eaf\u5185\u7f51 Web \u63a7\u5236\u667a\u80fd\u786c\u4ef6\u7684\u6280\u672f\u9009\u578b\u4e4b\u8def"},{"content":" \u81ea\u5df1\u6316\u7684\u5751\uff0c\u54ed\u7740\u4e5f\u8981\u586b\u5b8c\u3002\/\u7b11\u54ed\u8138\n 2018-03-11  \u4fee\u590d\u56fe\u7247\u672c\u5730\u5316\u9020\u6210\u5927\u91cf\u65e0\u7528\u9644\u4ef6\u95ee\u9898\u3002  2018-03-09  \u4fee\u590d\u7f29\u7565\u56fe\u6bd4\u4f8b\u62c9\u4f38\u95ee\u9898\uff0c\u903b\u8f91\u91cd\u6784\u3002  2018-02-21  \u6839\u636e Lighthouse \u5efa\u8bae\u4fee\u590d\u90e8\u5206\u95ee\u9898\u3002 \u4fee\u590d\u79fb\u52a8\u7aef\u4e00\u5904 CSS \u6837\u5f0f\u95ee\u9898\u3002  2018-02-18  \u4fee\u590d\u6bcf\u65e5\u56fe\u7247\u672a\u91c7\u7528 HTTPS \u95ee\u9898\u3002 \u4f18\u5316 CDN \u7f13\u5b58\u89c4\u5219\uff0c\u52a0\u5feb\u8bbf\u95ee\u901f\u5ea6\u3002  2018-02-15  \u65b0\u589e\u300cBing \u6bcf\u65e5\u56fe\u7247\u300d\u7f13\u5b58\u529f\u80fd\uff0c\u964d\u4f4e\u8bbf\u95ee\u5ef6\u65f6\u3002  2018-02-14  \u56e0\u539f\u300c\u4e00\u8a00\u300d\u63a5\u53e3\u5931\u6548\uff0c\u6545\u8c03\u6574\u4e3a\u300cBing \u6bcf\u65e5\u56fe\u7247\u300d\u3002 \u4fee\u590d\u5bfc\u822a\u680f\u6d6e\u52a8\u6548\u679c\u5f02\u5e38\u3002  2017-11-20  \u8c03\u6574\u53f3\u4fa7\u8fb9\u680f\u6a21\u5757\u5b57\u4f53\u5927\u5c0f\u3002  2017-11-17  \u4fee\u590d\u4e00\u5904\u56e0\u52a0\u8f7d HTTP \u534f\u8bae\u8d44\u6e90\u5f15\u8d77\u7684\u8b66\u544a\u3002  2017-11-15  \u65b0\u589e\u652f\u6301\u539f\u751f Markdown \u5b58\u50a8\u3002  2017-11-11  \u542f\u7528\u65b0\u57df\u540d\u300cjootu.org\u300d\u3002  2017-11-10  \u4fee\u590d\u6587\u672c URL \u81ea\u52a8\u94fe\u63a5\u7684\u95ee\u9898\u3002 \u4fee\u590d\u90e8\u5206 Title \u9519\u8bef\u3002 \u4f18\u5316\u51e0\u4e2a\u56fa\u5b9a\u9875\u9762\u6587\u6848\u3002  2017-11-09  \u4f18\u5316\u517c\u5bb9 HTTP \u4e0e HTTPS \u534f\u8bae\u3002 \u4fee\u590d\u975e\u56fa\u5b9a\u57df\u540d\u65e0\u9650 302 \u8df3\u8f6c\u3002 \u4fee\u590d\u51e0\u5904\u6837\u5f0f\u95ee\u9898\u3002  2017-11-04  \u4f18\u5316\u4ee3\u7801\u663e\u793a\u5b57\u4f53\u3002 \u4fee\u590d Meta \u6807\u7b7e\u591a\u5904 Author \u663e\u793a\u9519\u8bef\u95ee\u9898\u3002 \u7edf\u4e00\u4f5c\u8005\u540d\u79f0\u663e\u793a\u3002 \u65b0\u589e\u6587\u7ae0\u5e95\u90e8\u4f5c\u8005\u6a21\u5757\u3002  2017-10-28  \u4fee\u590d\u56fe\u7247\u6c34\u5370\u8fc7\u5927\u65e0\u6cd5\u751f\u6548\u7684\u95ee\u9898\u3002 \u8c03\u6574\u56fe\u50cf\u538b\u7f29\u7b97\u6cd5\u3002 \u4fee\u590d\u7f16\u8f91\u5668\u4e0a\u4f20\u56fe\u7247\u6587\u4ef6\u540d\u7b97\u6cd5\u3002  2017-10-27  \u4fee\u590d\u4f5c\u8005\u65e0\u6743\u9650\u8bbe\u7f6e\u6807\u7b7e\u95ee\u9898\u3002 \u8c03\u6574\u6807\u7b7e\u5217\u8868\u6392\u5e8f\u3002  2017-10-26  \u4fee\u590d\u641c\u7d22\u65e0\u7ed3\u679c\u65f6\u7684\u62a5\u9519\u3002 \u65b0\u589e\u4e00\u8a00\u3002 \u65b0\u589e\u6807\u7b7e\u3002 \u65b0\u589e\u4f5c\u8005\u6587\u7ae0\u6d4f\u89c8\u91cf\u7edf\u8ba1\u3002 \u4fee\u590d\u975e\u7ba1\u7406\u5458\u516c\u544a\u680f\u53f3\u4fa7\u4e0d\u663e\u793a\u63a7\u5236\u53f0\u7684\u95ee\u9898\u3002 \u4fee\u590d code \u6807\u7b7e\u6837\u5f0f\u4e0d\u6b63\u5e38\u95ee\u9898\u3002  2017-10-25  \u4fee\u590d\u4e00\u5904\u53ef\u80fd\u7684\u4e25\u91cd\u5b89\u5168\u6f0f\u6d1e\u3002 \u65b0\u589e\u56fe\u7247\u5ef6\u8fdf\u52a0\u8f7d\u529f\u80fd\u3002 \u7f8e\u5316\u540e\u53f0\u754c\u9762\u3002 \u8c03\u6574\u540e\u53f0\u6587\u7ae0\u6807\u7b7e\u7f16\u8f91\u6846\u4f4d\u7f6e\u5230\u9876\u90e8\u3002 \u4fee\u590d\u6807\u7b7e\u4e3a\u5f3a\u5236\u5c0f\u5199\u907f\u514d\u5927\u5c0f\u5199\u6b67\u4e49\u95ee\u9898\u3002 \u4fee\u6539\u6587\u7ae0\u6458\u8981\u7b97\u6cd5\u4f7f\u7528 mb \u7cfb\u5217\u51fd\u6570\u3002  2017-10-24  \u4fee\u590d\u91cd\u5199\u89c4\u5219\u548c CDN \u7f13\u5b58\u89c4\u5219\u914d\u7f6e\u4e0d\u5f53\u5f15\u8d77\u7684\u6587\u7ae0\u6d88\u5931\u95ee\u9898\u3002 \u4f18\u5316\u6587\u7ae0\u6458\u8981\u81ea\u52a8\u63d0\u53d6\u7b97\u6cd5\u3002  2017-10-20  \u4fee\u590d\u6587\u7ae0\u9875\uff0f\u5217\u8868\u672a\u663e\u793a\u4f5c\u8005\u540d\u79f0\u7684\u95ee\u9898\u3002 \u4fee\u590d\u641c\u7d22\u9875\u65e0\u53f3\u4fa7\u8fb9\u680f\u7684\u95ee\u9898 \u4fee\u590d\u641c\u7d22\u9875\u70ed\u95e8\u6587\u7ae0\u6a21\u5757\u65e0\u6548\u95ee\u9898\u3002 \u4fee\u590d\u6587\u7ae0 ID \u95f4\u65ad\uff08\u4e0d\u8fde\u7eed\uff09\u65f6\u968f\u673a\u70ed\u95e8\u6587\u7ae0\u7f3a\u5931\u95ee\u9898\u3002  2017-10-19  \u4fee\u590d\u5bfc\u822a\u680f\u56e0\u5b57\u4f53\u4e2d\u82f1\u6587\u4e0d\u7b49\u9ad8\u5f15\u8d77\u7684\u70ed\u70b9\u80cc\u666f\u8272\u53d8\u5316\u672a\u94fa\u6ee1\u7684\u95ee\u9898\u3002 \u4fee\u590d\u9a8c\u8bc1\u7801\u63d2\u4ef6\u65e0\u6cd5\u9a8c\u8bc1\u7684\u95ee\u9898\u3002 \u4fee\u6539\u968f\u673a\u6587\u7ae0\u7279\u8272\u56fe\u3002  2017-10-18  \u4fee\u590d parsedown \u89e3\u6790 bug \u5f15\u8d77\u7684\u65e0\u5e8f\u5217\u8868 last item \u672a\u5305\u542b p \u6807\u7b7e\u95ee\u9898\u3002 \u4fee\u590d css \u65e0\u5e8f\u5217\u8868\u4e0d\u663e\u793a\u5c0f\u5706\u70b9\u7684\u95ee\u9898\u3002 \u589e\u52a0\u56fe\u7247\u6c34\u5370\uff0c\u4fee\u590d logo \u7b49\u8bbe\u8ba1\u95ee\u9898\u3002  \u66f4\u65e9  \u4fee\u6539 zbp \u4f5c\u8005\u5217\u8868\u4e3a\u6309\u7167\u6587\u7ae0\u6570\u91cf\u6392\u5e8f\u3002 \u66ff\u6362 UEditor \u4e3a Editor.md\u3002 \u4f18\u5316\u7f29\u7565\u56fe\u63d2\u4ef6\u91cd\u5199\u89c4\u5219\u3002 \u4fee\u590d\u6b64\u4e3b\u9898 bug \u5341\u591a\u5904\uff1b\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\uff1a\u6587\u7ae0\u7279\u8272\u56fe\u7f29\u7565\u5c3a\u5bf8\u95ee\u9898\uff0f\u9ed8\u8ba4\u968f\u673a\u7279\u8272\u56fe\u95ee\u9898\uff0f\u6587\u7ae0\u9875 title \u5305\u542b\u5206\u7c7b\u7684\u95ee\u9898\uff0f\u6587\u7ae0\u63cf\u8ff0\u5931\u6548\u7684\u95ee\u9898\u2026\u2026  ","permalink":"https:\/\/wi1dcard.dev\/posts\/jootu-blog-change-log\/","summary":"\u81ea\u5df1\u6316\u7684\u5751\uff0c\u54ed\u7740\u4e5f\u8981\u586b\u5b8c\u3002\/\u7b11\u54ed\u8138\n 2018-03-11  \u4fee\u590d\u56fe\u7247\u672c\u5730\u5316\u9020\u6210\u5927\u91cf\u65e0\u7528\u9644\u4ef6\u95ee\u9898\u3002  2018-03-09  \u4fee\u590d\u7f29\u7565\u56fe\u6bd4\u4f8b\u62c9\u4f38\u95ee\u9898\uff0c\u903b\u8f91\u91cd\u6784\u3002  2018-02-21  \u6839\u636e Lighthouse \u5efa\u8bae\u4fee\u590d\u90e8\u5206\u95ee\u9898\u3002 \u4fee\u590d\u79fb\u52a8\u7aef\u4e00\u5904 CSS \u6837\u5f0f\u95ee\u9898\u3002  2018-02-18  \u4fee\u590d\u6bcf\u65e5\u56fe\u7247\u672a\u91c7\u7528 HTTPS \u95ee\u9898\u3002 \u4f18\u5316 CDN \u7f13\u5b58\u89c4\u5219\uff0c\u52a0\u5feb\u8bbf\u95ee\u901f\u5ea6\u3002  2018-02-15  \u65b0\u589e\u300cBing \u6bcf\u65e5\u56fe\u7247\u300d\u7f13\u5b58\u529f\u80fd\uff0c\u964d\u4f4e\u8bbf\u95ee\u5ef6\u65f6\u3002  2018-02-14  \u56e0\u539f\u300c\u4e00\u8a00\u300d\u63a5\u53e3\u5931\u6548\uff0c\u6545\u8c03\u6574\u4e3a\u300cBing \u6bcf\u65e5\u56fe\u7247\u300d\u3002 \u4fee\u590d\u5bfc\u822a\u680f\u6d6e\u52a8\u6548\u679c\u5f02\u5e38\u3002  2017-11-20  \u8c03\u6574\u53f3\u4fa7\u8fb9\u680f\u6a21\u5757\u5b57\u4f53\u5927\u5c0f\u3002  2017-11-17  \u4fee\u590d\u4e00\u5904\u56e0\u52a0\u8f7d HTTP \u534f\u8bae\u8d44\u6e90\u5f15\u8d77\u7684\u8b66\u544a\u3002  2017-11-15  \u65b0\u589e\u652f\u6301\u539f\u751f Markdown \u5b58\u50a8\u3002  2017-11-11  \u542f\u7528\u65b0\u57df\u540d\u300cjootu.","title":"\u6280\u672f\u535a\u5ba2\u586b\u5751\u4e4b\u8def"},{"content":" PHP GD \u6269\u5c55\u63d0\u4f9b\u4e86\u56fe\u50cf\u5904\u7406\u7684\u63a5\u53e3\uff0c\u672c\u6587\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u4e00\u6b3e\u975e\u5e38\u5c0f\u5de7\u6613\u7528\u7684\u7f29\u7565\u56fe\u5e93\uff0c\u652f\u6301\u591a\u79cd\u7f29\u653e\u65b9\u5f0f\u3001\u591a\u79cd\u8f93\u51fa\u683c\u5f0f\u3001\u81ea\u5e26\u7f13\u5b58\u914d\u7f6e\u2026\u2026\n 0x00 \u6e90\u7801 \u9996\u5148\u5f53\u7136\u662f\u653e\u6e90\u7801\uff1a\nwi1dcard\/Thumb\n\u539f\u4f5c\u8005\u4ee3\u7801\u56e0\u4e3a\u591a\u5e74\u6ca1\u6709\u7ef4\u62a4\uff0c\u6211\u8fdb\u884c\u4e86\u5927\u91cf\u8c03\u6574\u548c\u4f18\u5316\uff0c\u6682\u65f6\u5c31\u4e0d\u5408\u5e76\u4e86\u3002\n0x01 \u4f7f\u7528 \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u5c06thumb.php\u590d\u5236\u5230 Web \u670d\u52a1\u5668\u76ee\u5f55\u4e0b\uff0c\u6253\u5f00\u6b64\u6587\u4ef6\u3002\u6587\u4ef6\u5934\u90e8\u63d0\u4f9b\u4e00\u4e9b\u53ef\u4f9b\u4fee\u6539\u7684\u53c2\u6570\uff0c\u5305\u62ec\u7f13\u5b58\u76ee\u5f55\u7b49\u3002\n\u6211\u4eec\u5728\u6b64\u76ee\u5f55\u4e0b\u521b\u5efacache\u6587\u4ef6\u5939\uff0c\u5e76\u786e\u4fdd PHP \u62e5\u6709rw\u6743\u9650\u3002\n\u63a5\u4e0b\u6765\uff0c\u968f\u4fbf\u627e\u4e00\u5f20\u56fe\u7247\u653e\u5728\u6b64\u76ee\u5f55\u4e0b\uff0c\u63a5\u7740\u4f7f\u7528 Postman \u8bbf\u95ee\uff1a\nhttp:\/\/&lt;YOUR_HOST&gt;\/thumb.php?src=&lt;IMG_SRC&gt;&amp;size=&lt;Width&gt;x&lt;Height&gt;\n\u4f8b\u5982\uff1a\nhttp:\/\/localhost\/thumb.php?src=test.png&amp;size=100x200\n \u4f7f\u7528 Postman \u662f\u4e3a\u907f\u514d\u5ba2\u6237\u7aef\u7f13\u5b58\u751f\u6548\u3002\n \u53ef\u4ee5\u53d1\u73b0\u5df2\u7ecf\u6210\u529f\u8f93\u51fa\u7f29\u7565\u56fe\uff0c\u4e14\u5728cache\u6587\u4ef6\u5939\u4e0b\u6709\u4e00\u6761\u7f13\u5b58\u6587\u4ef6\u4ea7\u751f\u3002\u5f53\u4e0b\u4e00\u6b21\u8fdb\u884c\u8bf7\u6c42\u65f6\uff0cThumb\u4f1a\u81ea\u52a8\u68c0\u6d4b\u5ba2\u6237\u7aef\u7f13\u5b58\uff0c\u82e5\u5b58\u5728\u5219\u8fd4\u56deHTPP Status 304\uff0c\u82e5\u4e0d\u5b58\u5728\u5219\u68c0\u6d4b\u670d\u52a1\u7aef\u7f29\u7565\u56fe\u7f13\u5b58\uff08cache\u6587\u4ef6\u5939\uff09\uff0c\u82e5\u5df2\u5b58\u5728\u5bf9\u5e94\u56fe\u7247\u3001\u7f29\u7565\u56fe\u53c2\u6570\u7684\u7f13\u5b58\uff0c\u5219\u76f4\u63a5\u8fd4\u56de\u7f13\u5b58\uff0c\u4e0d\u91cd\u65b0\u8fdb\u884c\u56fe\u7247\u5904\u7406\u3002\n0x02 \u62d3\u5c55 \u5173\u4e8e\u66f4\u591a\u7f29\u7565\u56fe\u7684\u53c2\u6570\uff0c\u53ef\u53c2\u8003 README \u6587\u6863\u8bf4\u660e\u3002\n\u53e6\u5916\uff0c\u6b64\u5e93\u5355\u6587\u4ef6\u4e14\u5185\u90e8\u96c6\u6210\u7f13\u5b58\u7684\u65b9\u5f0f\u7684\u786e\u8ba9\u7f29\u7565\u56fe\u53d8\u5f97\u7b80\u5355\u6613\u7528\uff0c\u4f46\u540c\u6837\u5b58\u5728\u4e00\u4e9b\u95ee\u9898\uff1a\u65e0\u8bba\u56fe\u7247\u662f\u5426\u5df2\u88ab\u7f13\u5b58\uff0c\u6240\u6709\u7684\u7f29\u7565\u56fe\u8bf7\u6c42\u90fd\u4f1a\u8fdb\u5165\u5230 PHP \u4ee3\u7801\u5185\u8fdb\u884c\u5904\u7406\uff0c\u65e0\u7591\u4f1a\u589e\u52a0\u4e0d\u5fc5\u8981\u7684\u8d44\u6e90\u6d88\u8017\u3002\n\u5bf9\u4e8e\u8bf7\u6c42\u8bbf\u95ee\u91cf\u6bd4\u8f83\u5927\u7684\u7ad9\u70b9\uff0c\u8fd8\u662f\u80fd\u5728 Web \u670d\u52a1\u5668\u5904\u7406\u6389\u7684\u8bf7\u6c42\uff0c\u5c31\u76f4\u63a5\u5904\u7406\u6389\u6bd4\u8f83\u597d\uff0c\u5c24\u5176\u50cf\u8fd9\u7c7b\u9759\u6001\u6587\u4ef6\uff0c\u7edd\u5bf9\u662f Nginx \u7684\u5f3a\u9879\u3002\n\u4f60\u53ef\u4ee5\u5c06\u8bf7\u6c42 URL \u6539\u4e3a\u56fe\u7247\u540e\u7f00\u540d\u7ed3\u5c3e\uff08\u4f8b\u5982\uff1axxx.jpg\uff09\uff0c\u5229\u7528 Nginx \u7684try_files\u6307\u4ee4\uff0c\u5c1d\u8bd5\u8bbf\u95ee\u6e90\u6587\u4ef6\uff0c\u4e0d\u5b58\u5728\u518d\u8d70\u7f29\u7565\u56fe\u5e93\u3002\n\u5f53\u7136\uff0c\u5982\u4eca\u4e5f\u6709 Nginx \u76f4\u63a5\u5b9e\u73b0\u7f29\u7565\u56fe\u7684\u6a21\u5757\uff0cGitHub \u4e0a\u641c\u7d22\u5173\u952e\u8bcd\uff1athumb nginx\u3002\u4e0d\u8fc7\u9700\u8981\u91cd\u65b0\u7f16\u8bd1 Nginx\uff0c\u7565\u663e\u9ebb\u70e6\u3002\n\u8fd8\u6709\u4e00\u4e2a\u6bd4\u8f83\u61d2\u7684\u529e\u6cd5\u2014\u2014\u6302 CDN\uff0c\u7f13\u5b58\u5168\u90e8thumb.php\u8bf7\u6c42\u3002\n0x03 \u611f\u8a00 \u6761\u6761\u5927\u8def\u901a\u7f57\u9a6c\uff0c\u4f17\u591a\u6280\u672f\u65b9\u6848\u9762\u524d\uff0c\u5b9e\u73b0\u5bb9\u6613\uff0c\u9009\u62e9\u5408\u9002\u7684\u624d\u662f\u96be\u70b9\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php-thumb\/","summary":"PHP GD \u6269\u5c55\u63d0\u4f9b\u4e86\u56fe\u50cf\u5904\u7406\u7684\u63a5\u53e3\uff0c\u672c\u6587\u4e3a\u5927\u5bb6\u4ecb\u7ecd\u4e00\u6b3e\u975e\u5e38\u5c0f\u5de7\u6613\u7528\u7684\u7f29\u7565\u56fe\u5e93\uff0c\u652f\u6301\u591a\u79cd\u7f29\u653e\u65b9\u5f0f\u3001\u591a\u79cd\u8f93\u51fa\u683c\u5f0f\u3001\u81ea\u5e26\u7f13\u5b58\u914d\u7f6e\u2026\u2026\n 0x00 \u6e90\u7801 \u9996\u5148\u5f53\u7136\u662f\u653e\u6e90\u7801\uff1a\nwi1dcard\/Thumb\n\u539f\u4f5c\u8005\u4ee3\u7801\u56e0\u4e3a\u591a\u5e74\u6ca1\u6709\u7ef4\u62a4\uff0c\u6211\u8fdb\u884c\u4e86\u5927\u91cf\u8c03\u6574\u548c\u4f18\u5316\uff0c\u6682\u65f6\u5c31\u4e0d\u5408\u5e76\u4e86\u3002\n0x01 \u4f7f\u7528 \u4f7f\u7528\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\uff0c\u5c06thumb.php\u590d\u5236\u5230 Web \u670d\u52a1\u5668\u76ee\u5f55\u4e0b\uff0c\u6253\u5f00\u6b64\u6587\u4ef6\u3002\u6587\u4ef6\u5934\u90e8\u63d0\u4f9b\u4e00\u4e9b\u53ef\u4f9b\u4fee\u6539\u7684\u53c2\u6570\uff0c\u5305\u62ec\u7f13\u5b58\u76ee\u5f55\u7b49\u3002\n\u6211\u4eec\u5728\u6b64\u76ee\u5f55\u4e0b\u521b\u5efacache\u6587\u4ef6\u5939\uff0c\u5e76\u786e\u4fdd PHP \u62e5\u6709rw\u6743\u9650\u3002\n\u63a5\u4e0b\u6765\uff0c\u968f\u4fbf\u627e\u4e00\u5f20\u56fe\u7247\u653e\u5728\u6b64\u76ee\u5f55\u4e0b\uff0c\u63a5\u7740\u4f7f\u7528 Postman \u8bbf\u95ee\uff1a","title":"Thumb - \u81ea\u5e26\u7f13\u5b58\u914d\u7f6e\u7684\u5355\u6587\u4ef6 PHP \u7f29\u7565\u56fe\u5e93"},{"content":" \u4e0d\u77e5\u4e0d\u89c9\u642d\u5efa\u6280\u672f\u535a\u5ba2\u5df2\u7ecf\u8fc7\u53bb\u534a\u5e74\uff0c\u534a\u5e74\u6765\u81ea\u5df1\u548c\u56e2\u961f\u5171\u540c\u8fdb\u6b65\u6210\u957f\uff0c\u4e5f\u5e26\u52a8\u7f51\u7ad9\u5185\u5bb9\u6c34\u51c6\u8d8a\u6765\u8d8a\u9ad8\uff1b\u5728\u6b64\u5c0f\u7ed3\u4e00\u4e0b\u534a\u5e74\u6765\u6df1\u5ea6\u4f7f\u7528 Z-Blog \u4f53\u4f1a\u5230\u7684\u4f18\u7f3a\u70b9\uff0c\u5e0c\u671b\u80fd\u591f\u7ed9\u4e88\u540e\u6765\u8005\u4e00\u5b9a\u53c2\u8003\u3002\n 0x00 \u8bf4\u5230\u535a\u5ba2\uff0c\u4e0d\u5f97\u4e0d\u63d0\u8d77\u4e24\u4e2a\u94fe\u63a5\uff1a\n  \u5173\u4e8e\u672c\u7ad9\n  \u586b\u5751\u4e4b\u8def\n  \u7684\u786e\uff0c\u65f6\u95f4\u8fc7\u5f97\u5f88\u5feb\u3002\n0x01 \u5982\u4e0a\uff0c\u5728\u9009\u7528 Z-Blog \u65f6\uff0c\u5954\u7740\u8fd9\u51e0\u70b9\u53bb\u7684\uff1a\n \u5b98\u65b9\u63d2\u4ef6\u4e2d\u5fc3\u3001\u4e3b\u9898\u4e2d\u5fc3\uff0c\u4fbf\u4e8e\u5b89\u88c5\u4f7f\u7528\u3002 \u7b2c\u4e09\u65b9\u5f00\u53d1\u8005\u4e0d\u5c11\uff0c\u63d2\u4ef6\u4f17\u591a\u3002 \u652f\u6301\u591a\u7528\u6237\u548c\u6743\u9650\u7ba1\u7406\u3002 \u8f7b\u91cf\uff08\u76f8\u6bd4 WordPress\uff09\u3002 \u6709 Markdown \u63d2\u4ef6\u3002  \u540e\u6765\u53d1\u73b0\uff0c\u4e8b\u60c5\u5e76\u6ca1\u6709\u90a3\u4e48\u7b80\u5355\u2026\u2026\n\u867d\u7136\u622a\u81f3\u76ee\u524d\u6765\u770b\uff0c\u4ee5\u4e0a\u6240\u5217\u4f18\u70b9\u7684\u786e\u5982\u6b64\u3002\n Markdown \u63d2\u4ef6\u5728\u6211\u5b89\u88c5\u7684\u65f6\u5019\uff0c\u7248\u672c\u6bd4\u8f83\u4f4e\uff0cBug \u4e5f\u4e0d\u5c11\u3002\u4e0d\u8fc7\u540e\u6765\u4e00\u76f4\u5728\u6301\u7eed\u66f4\u65b0\uff0c\u65b0\u7248\u6211\u6ca1\u6709\u7528\u8fc7\uff08\u56e0\u4e3a\u6211\u6539\u8fc7\u4ed6\u4ee3\u7801\uff09\uff0c\u770b\u8d77\u6765\u4f3c\u4e4e\u4e0d\u9519\u3002\n \u4f46\u95ee\u9898\u540c\u6837\u4e0d\u5c11\uff0c\u5c31\u50cf\u521a\u521a\u8bf4\u7684\u90a3\u6837\u2014\u2014\u53ea\u662f\u56e0\u4e3a\u81ea\u5df1\u6539\u8fc7\u4ee3\u7801\uff0c\u4fee\u590d\u90e8\u5206 Issue\uff0c\u4f46\u63d2\u4ef6\u6ca1\u6709\u4f7f\u7528\u6e90\u4ee3\u7801\u6258\u7ba1\uff0c\u6240\u4ee5\u538b\u6839\u627e\u4e0d\u5230\u5730\u65b9\u901a\u77e5\u4f5c\u8005\uff0c\u66f4\u522b\u60f3\u7528 Git \u534f\u4f5c\u7ef4\u62a4\u9879\u76ee\u2026\u2026\n\u5c2c\uff01\u96be\u4e0d\u6210\u8ba9\u6211\u7528 Beyond Compare \u624b\u52a8\u5408\uff1f\nemmm\uff0c\u6211\u4f1a\u8003\u8651\u4e00\u4e0b\u7684\u3002\n\ud83d\ude11\ud83d\ude44\n0x02 \u901a\u8fc7\u8fd9\u4e00\u4e2a\u4f8b\u5b50\uff0c\u4e5f\u53ef\u4ee5\u770b\u51fa\u80cc\u540e\u4e00\u4e9b\u66f4\u6df1\u5c42\u6b21\u7684\u95ee\u9898\uff1a\n  \u7b2c\u4e09\u65b9\u5f00\u53d1\u8005\u6c34\u5e73\u53c2\u5dee\u4e0d\u9f50\uff0c\u65e0\u4ee3\u7801\u7ba1\u7406\u6982\u5ff5\u3002\n  \u793e\u533a\u3001\u8bba\u575b\u3001\u7fa4\u804a\u751f\u6001\u73af\u5883\u5dee\u3002\n  \u800c\u8fd9\u4e00\u5c42\u518d\u80cc\u540e\uff0c\u6216\u8bb8\u80fd\u5f15\u51fa\u80fd\u9ad8\u5c42\u6b21\u3001\u66f4\u6df1\u5965\u7684\u300c\u79d8\u5bc6\u300d\uff1f\n\u6216\u8bb8\u8fd9\u662f\u56fd\u5185\u8f6f\u4ef6\u884c\u4e1a\u300c\u5f15\u4ee5\u4e3a\u50b2\u300d\u7684\u73b0\u72b6\uff1f\n\u5ffd\u7136\u60f3\u8d77\u5f53\u5e74 SS \u4f5c\u8005\u6012\u6495 SSR \u4e0d\u5f00\u6e90\u4e8b\u4ef6\u7684\u4e00\u6bb5\u5bf9\u8bdd\uff0c\u81ea\u884c\u4f53\u4f1a\u3002\n0x03 \u6700\u540e\uff0c\u5bf9\u4e8e Z-Blog \u672c\u8eab\u3002\u76ee\u524d\u6765\u770b\uff0c\u6211\u8ba4\u4e3a\u5b83\u8fd8\u662f\u7ecf\u5f97\u8d77\u8003\u9a8c\u7684\u4e00\u6b3e\u597d\u4ea7\u54c1\u3002\u7ecf\u8fc7\u4e00\u8f6e\u53c8\u4e00\u8f6e\u5730\u8c03\u8bd5\u3001\u4fee\u590d\uff0c\u6211\u6781\u5c11\u3001\u51e0\u4e4e\u6ca1\u6709\u4fee\u6539\u8fc7 ZB \u6e90\u7801\u3002\u534a\u5e74\u4ee5\u6765\uff0c\u5355\u6b21\u8bf7\u6c42\u5e73\u5747\u5185\u5b58\u6d88\u8017\u91cf\u4e00\u76f4\u7ef4\u6301\u5728 4MB \u4e0a\u4e0b\uff0c\u800c\u7ecf\u8fc7\u63d2\u4ef6\u8c03\u4f18\u7684\u8bf7\u6c42\u54cd\u5e94\u65f6\u95f4\u4e5f\u80fd\u591f\u5f88\u8f7b\u677e\u5730\u63a7\u5236\u5728 50ms \u4ee5\u5185\u3002\u53e6\u5916\uff0cZB \u6269\u5c55\u6027\u4e5f\u4e0d\u5dee\uff0c\u8ba4\u771f\u9605\u8bfb\u63d2\u4ef6\u5f00\u53d1\u6587\u6863\uff0c\u591a\u6570\u529f\u80fd\u90fd\u80fd\u5f97\u5230\u4f18\u96c5\u7684\u5b9e\u73b0\u3002\n\u81f3\u4e8e\u63d2\u4ef6\uff0c\u8fd8\u662f\u80fd\u7701\u5219\u7701\u5427\u3002\u6700\u540e\u5217\u51fa\u76ee\u524d\u6211\u4eec\u6240\u4f7f\u7528\u7684\u63d2\u4ef6\u5217\u8868\uff0c\u51e0\u4e4e\u5168\u90e8\u88ab\u4fee\u6539\u8fc7\uff0c\u4ec5\u4f9b\u53c2\u8003\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/zblog-pros-and-cons\/","summary":"\u4e0d\u77e5\u4e0d\u89c9\u642d\u5efa\u6280\u672f\u535a\u5ba2\u5df2\u7ecf\u8fc7\u53bb\u534a\u5e74\uff0c\u534a\u5e74\u6765\u81ea\u5df1\u548c\u56e2\u961f\u5171\u540c\u8fdb\u6b65\u6210\u957f\uff0c\u4e5f\u5e26\u52a8\u7f51\u7ad9\u5185\u5bb9\u6c34\u51c6\u8d8a\u6765\u8d8a\u9ad8\uff1b\u5728\u6b64\u5c0f\u7ed3\u4e00\u4e0b\u534a\u5e74\u6765\u6df1\u5ea6\u4f7f\u7528 Z-Blog \u4f53\u4f1a\u5230\u7684\u4f18\u7f3a\u70b9\uff0c\u5e0c\u671b\u80fd\u591f\u7ed9\u4e88\u540e\u6765\u8005\u4e00\u5b9a\u53c2\u8003\u3002\n 0x00 \u8bf4\u5230\u535a\u5ba2\uff0c\u4e0d\u5f97\u4e0d\u63d0\u8d77\u4e24\u4e2a\u94fe\u63a5\uff1a\n  \u5173\u4e8e\u672c\u7ad9\n  \u586b\u5751\u4e4b\u8def\n  \u7684\u786e\uff0c\u65f6\u95f4\u8fc7\u5f97\u5f88\u5feb\u3002\n0x01 \u5982\u4e0a\uff0c\u5728\u9009\u7528 Z-Blog \u65f6\uff0c\u5954\u7740\u8fd9\u51e0\u70b9\u53bb\u7684\uff1a","title":"\u534a\u5e74\u5c0f\u8bb0\uff1aZ-Blog \u7684\u4f18\u52bf\u52a3\u52bf"},{"content":" \u603b\u7ed3\u90e8\u5206 FFmpeg \u5e38\u7528\u547d\u4ee4\u884c\u4ee5\u5907\u67e5\u8be2\u4e4b\u7528\u3002\n \u76f4\u63a8\uff08H.264 + AAC\uff09 ffmpeg -re -i INPUT_FILE_NAME -c copy -f flv rtmp:\/\/localhost\/live\/STREAM_NAME\n\u8f6c\u7801\u63a8 ffmpeg -re -i INPUT_FILE_NAME -c:v libx264 -preset superfast -tune zerolatency -c:a aac -f flv rtmp:\/\/localhost\/live\/STREAM_NAME\n\u8f6c\u7801\u63a8\uff08\u6539\u53d8\u97f3\u9891\u91c7\u6837\u7387\uff09 -ar 44100\n\u8f6c\u7801\u63a8\uff08\u6539\u53d8\u89c6\u9891\u5bbd\u9ad8\uff09 -s 1280*720\n\u8f6c\u7801\u63a8\uff08\u622a\u53d6\u6307\u5b9a\u65f6\u95f4\u6bb5\uff09 -ss 1:00:00 -t 00:00:10 -accurate_seek\uff08\u4ece ss \u5f00\u59cb\u622a\u53d6 t\uff09\nMore&hellip; FFmpeg \u5e38\u7528\u63a8\u6d41\u547d\u4ee4 \u4f7f\u7528 FFmpeg \u5c06\u5b57\u5e55\u6587\u4ef6\u96c6\u6210\u5230\u89c6\u9891\u6587\u4ef6 potplayer \u5f55\u5236&#43;ffmpeg \u63a8\u6d41\u5230\u76f4\u64ad\u95f4\u7684\u65b9\u6cd5\uff01 \u63a8\u6d41\u65b0\u6280\u80fd\uff0cpotplayer&#43;ffmpeg\n","permalink":"https:\/\/wi1dcard.dev\/posts\/ffmpeg-live-stream-useful-commands\/","summary":"\u603b\u7ed3\u90e8\u5206 FFmpeg \u5e38\u7528\u547d\u4ee4\u884c\u4ee5\u5907\u67e5\u8be2\u4e4b\u7528\u3002\n \u76f4\u63a8\uff08H.264 + AAC\uff09 ffmpeg -re -i INPUT_FILE_NAME -c copy -f flv rtmp:\/\/localhost\/live\/STREAM_NAME\n\u8f6c\u7801\u63a8 ffmpeg -re -i INPUT_FILE_NAME -c:v libx264 -preset superfast -tune zerolatency -c:a aac -f flv rtmp:\/\/localhost\/live\/STREAM_NAME","title":"FFmpeg \u76f4\u64ad\u63a8\u6d41\u5e38\u7528\u547d\u4ee4\u603b\u7ed3"},{"content":" Laravel + Swoole \u5b9e\u73b0\u66f4\u5feb\u7684\u8bf7\u6c42\u5904\u7406\u901f\u5ea6\u3001\u66f4\u9ad8\u5e76\u53d1\u6709\u6269\u5c55\u5305\u53ef\u4f9b\u9009\u62e9\uff0c\u90a3\u4e48\u5982\u4f55\u5728 Laravel \u6846\u67b6\u5185\u4f18\u96c5\u5730\u5d4c\u5165 Swoole \u5b9e\u73b0 TCP\/UDP Socket \u670d\u52a1\u7aef\u5462\uff1f\n 0x00 Why \u5148\u8bf4\u8bf4\u4e3a\u4ec0\u4e48\u8981\u5d4c\u5165 Laravel \u5427\u3002\n\u5c31\u4e00\u4e2a\u539f\u56e0\uff1a\nEloquent ORM\n\u7269\u8054\u7f51\u573a\u666f\u4e0b\uff0cSwoole \u4f5c\u4e3a\u4e0e\u786c\u4ef6\u5bf9\u63a5\u7684\u540e\u7aef\u670d\u52a1\uff0c\u63a5\u6536\u5230\u786c\u4ef6\u53d1\u6765\u7684\u6570\u636e\u5305\u540e\uff0c\u591a\u6570\u60c5\u51b5\u9700\u8981\u76f4\u63a5\u5165\u5e93\uff0c\u6240\u4ee5\u6709\u4e00\u4e2a\u65b9\u4fbf\u6613\u7528\u7684 ORM \u5c31\u663e\u5f97\u5c24\u4e3a\u91cd\u8981\u91cd\u8981\u3002\n\u800c\u76ee\u524d\u516c\u53f8\u7684\u60c5\u51b5\uff0c\u6211\u4eec\u4e0e Web \u7aef\u5bf9\u63a5\u7684\u540e\u7aef\u6846\u67b6\u662f Laravel\uff1b\u82e5\u662f\u80fd\u7ed3\u5408\u4e00\u4e0b\uff0c\u53c8\u80fd\u5229\u7528\u73b0\u6210\u7684\u6570\u636e\u6a21\u578b\uff0c\u4e0d\u9700\u8981\u518d\u91cd\u590d\u5b9a\u4e49\uff0c\u5c82\u4e0d\u662f\u7f8e\u6ecb\u6ecb\uff5e\n0x01 How \u9996\u5148\u521b\u5efa\u9879\u76ee\uff1alaravel new\n\u6839\u636e Server - Swoole \u6587\u6863\uff0c\u300cswoole_server \u53ea\u80fd\u7528\u4e8e php-cli \u73af\u5883\u300d\uff0c\u800c Laravel \u63d0\u4f9b\u7684 Artisan \u547d\u4ee4\u884c \u529f\u80fd\u5c31\u662f\u57fa\u4e8e PHP-CLI \u7684\uff1b\n\u6309\u7167\u8fd9\u4e2a\u601d\u8def\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u4e00\u6761\u540d\u4e3aswoole:start\u7684 Artisan Command\uff0c\u4e0d\u9700\u8981\u7834\u574f\u6846\u67b6\u539f\u6709\u7ed3\u6784\uff0c\u90e8\u7f72\u65f6\u53ea\u9700\u8981\u6267\u884c\u6b64\u547d\u4ee4\u542f\u52a8 Swoole \u670d\u52a1\u7aef\u76d1\u542c\u786c\u4ef6\u901a\u4fe1\u7aef\u53e3\u5373\u53ef\u3002\n0x01 Just do it\uff01 \u521b\u5efa\u547d\u4ee4\u7c7b php artisan make:command Swoole \u5176\u4e2d\uff0cSwoole \u662f\u7c7b\u540d\u3002\n\u4fee\u6539\u5fc5\u8981\u53c2\u6570 \u6267\u884c\u540e\u4f1a\u5728app\/Console\/Commands\/\u6587\u4ef6\u5939\u5185\u521b\u5efa\u4e00\u4e2a\u4e0e\u7c7b\u540d\u76f8\u540c\u7684 php \u6587\u4ef6\uff0c\u8fd9\u5c31\u662f\u4f60\u7684\u547d\u4ee4\u7c7b\u3002\n \/** * \u6267\u884c\u6b64\u547d\u4ee4\u65f6\u6240\u9700\u7684\u547d\u4ee4\u540d\u3002 * * @var string *\/ protected $signature = 'swoole:start'; \/** * \u6b64\u547d\u4ee4\u7684\u63cf\u8ff0\u3002 * * @var string *\/ protected $description = 'Command description'; \u5982\u4e0a\uff0c\u4f60\u53ef\u4ee5\u4fee\u6539\u6210\u5458\u53d8\u91cf\u5b9a\u4e49\u547d\u4ee4\u7684\u540d\u79f0\u548c\u63cf\u8ff0\u3002\n\u5f15\u7528\u6570\u636e\u5e93\u95e8\u9762\u6216\u6a21\u578b \u4f7f\u7528 Artisan \u521b\u5efa\u7684\u547d\u4ee4\u7c7b\u9ed8\u8ba4\u662f\u4e0d\u5f15\u7528\u6570\u636e\u5e93\u95e8\u9762\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5728\u6587\u4ef6\u5934\u90e8\u52a0\u5165\uff1a\nuse Illuminate\\Support\\Facades\\DB; \/\/\u6216\u8005\u4f60\u53ef\u4ee5 use \u6240\u9700\u7684 Model\uff1a use App\\User; \u5904\u7406\u6b64\u547d\u4ee4 \u4fee\u6539handle\u6210\u5458\u51fd\u6570\uff0c\u6b64\u65b9\u6cd5\u4f1a\u5728\u6b64\u547d\u4ee4\u88ab\u6267\u884c\u7684\u65f6\u5019\u8c03\u7528\uff0c\u52a0\u5165\u542f\u52a8 Swoole \u7684\u4ee3\u7801\u5373\u53ef\u3002\n \/** * Execute the console command. * * @return mixed *\/ public function handle() { $server = new \\swoole_server(&quot;127.0.0.1&quot;, 9503); \/\/ \u6536\u5230\u8fde\u63a5\u8bf7\u6c42 $server-&gt;on('connect', function ($server, $fd) { echo &quot;connection open: {$fd}\\n&quot;; \/\/\u6570\u636e\u5165\u5e93 DB::table('users')-&gt;insert( ['username' =&gt; 'testu', 'password' =&gt; 'testp'] ); }); \/\/ \u6536\u5230\u6570\u636e\u5305 $server-&gt;on('receive', function ($server, $fd, $reactor_id, $data) { $server-&gt;send($fd, &quot;Swoole: {$data}&quot;); $server-&gt;close($fd); }); \/\/ \u65ad\u5f00\u8fde\u63a5 $server-&gt;on('close', function ($server, $fd) { echo &quot;connection close: {$fd}\\n&quot;; }); \/\/ \u542f\u52a8\u670d\u52a1 $server-&gt;start(); } \u6ce8\u610f\uff1anew \\swoole_server(...);\u4e0d\u8981\u5fd8\u8bb0\u53cd\u659c\u7ebf\uff08\\\uff09\uff0c\u8fd9\u662f\u8868\u793a\u5728\u5168\u5c40\u547d\u540d\u7a7a\u95f4\u4e0b\u7684\u7c7b\uff0c\u5177\u4f53\u53ef\u67e5\u770b PHP \u6587\u6863\uff1a\u5168\u5c40\u7a7a\u95f4\u3002\n\u4ee5\u4e0a\u4ee3\u7801\u5373\u53ef\u5b9e\u73b0\uff0c\u5ba2\u6237\u7aef\u8fde\u63a5\u65f6\u7acb\u5373\u5411\u6570\u636e\u5e93\u52a0\u5165\u4e00\u6761\u8bb0\u5f55\u3002\n\u542f\u52a8 \u73b0\u5728\uff0c\u547d\u4ee4\u884c\u6267\u884cphp artisan swoole:start\uff0c\u4e0d\u4f1a\u6709\u4efb\u4f55\u8f93\u51fa\uff0c\u522b\u62c5\u5fc3\uff0c\u8fd9\u662f\u6b63\u5e38\u7684\uff0cSwoole \u5df2\u7ecf\u542f\u52a8\u4e86\u3002\n\u63a5\u7740\u65b0\u6253\u5f00\u4e00\u4e2a\u547d\u4ee4\u884c\u7a97\u53e3\uff0c\u6267\u884ctelnet 127.0.0.1 9503\u3002\n Telnet \u662f\u4e00\u4e2a\u7c7b\u4f3c SSH \u7684\u4e1c\u897f\uff0c\u73b0\u5728\u57fa\u672c\u5df2\u7ecf\u88ab\u6dd8\u6c70\uff0c\u4f46 Telnet \u5ba2\u6237\u7aef\u4ecd\u5e38\u7528\u6765\u6d4b\u8bd5 TCP \u8fde\u63a5\u3002\u66f4\u591a\u5173\u4e8e Telnet \u7684\u77e5\u8bc6\uff0c\u53ef\u53c2\u8003\uff1atelnet \u547d\u4ee4\n \u8fd9\u65f6\uff0c\u53ef\u4ee5\u770b\u5230\u6267\u884c Artisan \u547d\u4ee4\u7684\u7a97\u53e3\u4f1a\u8f93\u51fa\uff1a\nconnection open: 1 \u68c0\u67e5\u6570\u636e\u5e93\uff0c\u6570\u636e\u6210\u529f\u63d2\u5165\u3002\n\u5b8c\u6210\uff01\n0x02 More MacOS \u5b89\u88c5 Telnet brew install telnet\nMacOS \u5b89\u88c5 Swoole \u9996\u5148\u4f7f\u7528 brew list | grep php \u67e5\u770b\u4f60\u7535\u8111\u4e0a\u7684 PHP \u7248\u672c\u3002\n\u68c0\u7d22\u6240\u6709\u7684 Swoole\uff1a\nbrew search swoole\n\u6839\u636e\u4e0d\u540c PHP \u7248\u672c\u5b89\u88c5\u5bf9\u5e94 Swoole \u5373\u53ef\uff0c\u6211\u7684\u7535\u8111\u662fphp71\uff0c\u6240\u4ee5\u6267\u884c\uff1a\nbrew install php71-swoole\n0x03 The End \u6709\u7a7a\u4f1a\u8003\u8651\u5c01\u88c5\u4e2a\u6269\u5c55\u5305\u3002\n\u53e6\u5916\uff0c\u8d34\u51e0\u4e2a\u5f00\u5934\u63d0\u5230\u7684\u300c\u5229\u7528 Swoole \u5904\u7406 PHP \u8bf7\u6c42\u63d0\u5347 Laravel \u901f\u5ea6\u300d\u7684\u73b0\u6210\u6269\u5c55\u5305\uff1a\n  garveen\/laravoole\n  scil\/LaravelFly\n  hhxsv5\/laravel-s\n  ","permalink":"https:\/\/wi1dcard.dev\/posts\/swoole-in-laravel\/","summary":"Laravel + Swoole \u5b9e\u73b0\u66f4\u5feb\u7684\u8bf7\u6c42\u5904\u7406\u901f\u5ea6\u3001\u66f4\u9ad8\u5e76\u53d1\u6709\u6269\u5c55\u5305\u53ef\u4f9b\u9009\u62e9\uff0c\u90a3\u4e48\u5982\u4f55\u5728 Laravel \u6846\u67b6\u5185\u4f18\u96c5\u5730\u5d4c\u5165 Swoole \u5b9e\u73b0 TCP\/UDP Socket \u670d\u52a1\u7aef\u5462\uff1f\n 0x00 Why \u5148\u8bf4\u8bf4\u4e3a\u4ec0\u4e48\u8981\u5d4c\u5165 Laravel \u5427\u3002\n\u5c31\u4e00\u4e2a\u539f\u56e0\uff1a\nEloquent ORM","title":"Laravel + Swoole \u5b9e\u73b0 TCP-UDP Socket \u670d\u52a1\u7aef"},{"content":" \u4f7f\u7528 OpenSSL \u547d\u4ee4\u884c\u751f\u6210 HTTPS \u81ea\u7b7e\u8bc1\u4e66\u3002\n openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout cert.key -out cert.pem \u751f\u6210\u8fc7\u7a0b\u4e2d\uff0c\u8bf7\u6ce8\u610fCommon Name\u9700\u8981\u6b63\u786e\u586b\u5165\u9700\u8981\u4e0a HTTPS \u7684\u57df\u540d\uff0c\u6709\u4e8c\u7ea7\u57df\u540d\u4e5f\u8981\u5e26\u4e0a\u3002\u5176\u5b83\u4fe1\u606f\u968f\u610f\u5373\u53ef\u3002\nTips\uff1a\u751f\u4ea7\u73af\u5883\u8bf7\u52ff\u4f7f\u7528\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/openssl-generate-cert\/","summary":"\u4f7f\u7528 OpenSSL \u547d\u4ee4\u884c\u751f\u6210 HTTPS \u81ea\u7b7e\u8bc1\u4e66\u3002\n openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout cert.key -out cert.pem \u751f\u6210\u8fc7\u7a0b\u4e2d\uff0c\u8bf7\u6ce8\u610fCommon Name\u9700\u8981\u6b63\u786e\u586b\u5165\u9700\u8981\u4e0a HTTPS \u7684\u57df\u540d\uff0c\u6709\u4e8c\u7ea7\u57df\u540d\u4e5f\u8981\u5e26\u4e0a\u3002\u5176\u5b83\u4fe1\u606f\u968f\u610f\u5373\u53ef\u3002","title":"OpenSSL \u968f\u624b\u8bb0 - \u751f\u6210\u81ea\u7b7e\u8bc1\u4e66"},{"content":" Laravel \u96c6\u6210\u4f17\u591a\u5f00\u5305\u5373\u7528\u7684\u529f\u80fd, \u867d\u7136\u5b83\u771f\u7684\u5f88&quot;\u80d6&quot;, \u4f46\u8fd9\u5e76\u4e0d\u5f71\u54cd\u5b83\u662f\u4e2a\u597d\u6846\u67b6. \u672c\u7bc7\u6587\u7ae0\u5c06\u91c7\u7528 Laravel 5.6 \u7248\u672c\u7531\u6d45\u5165\u6df1\u4e3a\u5927\u5bb6\u6f14\u793a: \u5982\u4f55\u4f7f\u7528\u5185\u7f6e\u7684 Broadcast\uff08\u5e7f\u64ad\uff09\u529f\u80fd\u5b9e\u73b0\u4e0e\u5ba2\u6237\u7aef\u5b9e\u65f6\u901a\u4fe1.\n Tips: \u6b64\u4ed3\u5e93\u5b9e\u73b0\u672c\u6587\u4e2d\u7684 0x02 \u5e7f\u64ad \u4ee3\u7801\u3002\n0x00 \u51c6\u5907  \u5e7f\u64ad\u7cfb\u7edf - Laravel 5.6 \u4e2d\u6587\u6587\u6863 \u7528\u6237\u8ba4\u8bc1 - Laravel 5.6 \u4e2d\u6587\u6587\u6863 \u4e8b\u4ef6\u7cfb\u7edf - Laravel 5.6 \u4e2d\u6587\u6587\u6863 \u961f\u5217\u7cfb\u7edf - Laravel 5.6 \u4e2d\u6587\u6587\u6863 \u524d\u7aef\u6307\u5357 - Laravel 5.6 \u4e2d\u6587\u6587\u6863 tlaverdure\/laravel-echo-server  \u6ca1\u9519\uff0c\u8fd9\u662f\u4f60\u9700\u8981\u7684\u77e5\u8bc6\u50a8\u5907\u3002\n \u622a\u6b62\u672c\u6587\u53d1\u5e03\uff0cLaravel 5.6 \u4e2d\u6587\u6587\u6863\u5e76\u672a\u7ffb\u8bd1\u5b8c\u6210\uff0c\u4ea6\u53ef\u53c2\u7167 5.5 \u7248\u672c\u6587\u6863\uff0c\u7c7b\u540c\u3002\n \u56e0\u4e3a PHP \u672c\u8eab\u5e76\u4e0d\u652f\u6301 WebSocket\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u4e00\u4e2a\u80fd\u591f\u5c06\u300c\u670d\u52a1\u5668\u300d\u6570\u636e\u53d1\u7ed9\u300c\u5ba2\u6237\u7aef\u300d\u7684\u95f4\u63a5\u5c42\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5b9e\u73b0\u5b9e\u65f6\u901a\u4fe1\u53ef\u4ee5\u5927\u81f4\u5206\u4e3a\u4e24\u4e2a\u6b65\u9aa4\uff1a\n \u300cLaravel\u300d -&gt; \u300c\u95f4\u63a5\u5c42\u300d \u300c\u95f4\u63a5\u5c42\u300d-&gt;\uff08via WebSocket\uff09-&gt;\u300c\u5ba2\u6237\u7aef\u300d  \u81f3\u4e8e\u95f4\u63a5\u5c42\u6211\u4eec\u91c7\u7528\u4ec0\u4e48\u5b9e\u73b0\uff0c\u540e\u9762\u518d\u8bb2\u3002\n0x01 \u914d\u7f6e \u6839\u636e\u5982\u4e0a \u5e7f\u64ad\u7cfb\u7edf \u7684\u6587\u6863\uff0c\u6211\u4eec\u9996\u5148\u9700\u8981\u505a\u5982\u4e0b\u7684\u914d\u7f6e\u5de5\u4f5c\u3002\n(1) \u9996\u5148\uff0c\u4fee\u6539 config\/broadcasting.php \u6216 .env \u6587\u4ef6\u3002\u786e\u4fdd Broadcast Default Driver \u662f log\uff0c\u4ee5\u6253\u5f00\u6b64\u529f\u80fd\uff0c\u4e14\u4fbf\u4e8e\u6211\u4eec\u8c03\u8bd5\u3002\n(2) \u4f7f\u7528 Broadcast \u5e7f\u64ad\uff0c\u5fc5\u987b\u4e86\u89e3 Laravel \u7684 \u4e8b\u4ef6\u7cfb\u7edf\uff0c\u5b83\u4eec\u662f\u4e92\u76f8\u4f9d\u8d56\u7684\u3002\u63a5\u4e0b\u6765\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u53ef\u4ee5\u300c\u88ab\u5e7f\u64ad\u300d\u7684\u4e8b\u4ef6\u3002\n\u4fee\u6539 app\/Providers\/EventServiceProvider.php\uff0c\u5728\u6210\u5458\u53d8\u91cf $listen \u5185\u8ffd\u52a0\uff1a\n&#39;App\\Events\\OrderShipped&#39; =&gt; [ &#39;App\\Listeners\\SendShipmentNotification&#39;, ], \u8fd9\u91cc\u6211\u4eec\u5c06\u6b64\u4e8b\u4ef6\u547d\u540d\u4e3a OrderShipped\uff08\u8ba2\u5355\u5df2\u7ed3\u7b97\uff09\uff1b\u6267\u884c php artisan event:generate \u751f\u6210\u4e8b\u4ef6\u7c7b\u53ca\u5176\u76d1\u542c\u5668\u3002\n \u82e5\u662f\u9700\u8981\u5c06\u4e8b\u4ef6\u6267\u884c\uff08\u5373\u5e7f\u64ad\u5230\u5ba2\u6237\u7aef\uff09\u4fee\u6539\u4e3a\u5f02\u6b65\uff0c\u8bf7\u53c2\u8003\u5982\u4e0a \u961f\u5217\u7cfb\u7edf \u6587\u6863\u3002\n (3) \u4e3a\u4e86\u80fd\u8ba9\u4e8b\u4ef6\u300c\u88ab\u5e7f\u64ad\u300d\uff0c\u6211\u4eec\u9700\u8981\u8ba9\u4e8b\u4ef6\u7c7b\u7ee7\u627f ShouldBroadcast \u63a5\u53e3\u3002\n\u6253\u5f00 app\/Events\/OrderShipped.php\uff0c\u4fee\u6539\u7c7b\u5b9a\u4e49\u4e3a\uff1a\nclass OrderShipped implements ShouldBroadcast (4) ShouldBroadcast \u63a5\u53e3\u8981\u6c42\u5b9e\u73b0 broadcastOn \u65b9\u6cd5\uff0c\u7528\u4e8e\u544a\u77e5\u6846\u67b6\uff1a\u6b64\u4e8b\u4ef6\u5e94\u8be5\u88ab\u53d1\u9001\u5230\u54ea\u4e2a\u300c\u9891\u9053\u300d\u3002\n Laravel \u7684\u5e7f\u64ad\u7cfb\u7edf\u5141\u8bb8\u6709\u591a\u4e2a\u9891\u9053\u5b58\u5728\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u7528\u6237\u540d\u533a\u522b\u4e0d\u540c\u9891\u9053\uff0c\u8fd9\u6837\u4e0d\u540c\u7684\u7528\u6237\u6536\u542c\u4e0d\u540c\u9891\u9053\uff0c\u5373\u53ef\u83b7\u5f97\u4e0d\u540c\u6d88\u606f\uff0c\u4e5f\u5c31\u80fd\u5b9e\u73b0\u548c\u4e0d\u540c\u5ba2\u6237\u7aef\u8fdb\u884c\u5355\u72ec\u901a\u4fe1\u3002\n\u5f53\u7136\uff0c\u4f60\u4e5f\u53ef\u4ee5\u4efb\u610f\u547d\u540d\u9891\u9053\uff0c\u4f46\u6700\u597d\u5177\u6709\u6709\u4e00\u5b9a\u89c4\u5219\u3002\n \u56e0\u4e3a\u6211\u4eec\u521a\u521a\u4f7f\u7528 artisan \u547d\u4ee4\u751f\u6210\u7684\u4e8b\u4ef6\u4ee3\u7801\uff0c\u6240\u4ee5\u5728\u6587\u4ef6\u6700\u4e0b\u65b9\uff0c\u4f60\u5df2\u7ecf\u80fd\u591f\u770b\u5230 broadcastOn \u65b9\u6cd5\u7684\u5b9a\u4e49\u4e86\u3002\u6211\u4eec\u7a0d\u4f5c\u4fee\u6539\uff1a\npublic function broadcastOn() { return new Channel(&#39;orderStatus&#39;); } \u8fd9\u91cc\u6211\u4eec\u5c06\u9891\u9053\u547d\u540d\u4e3a\uff1aorderStatus\uff0c\u5e76\u8fd4\u56de\u3002\u4e5f\u5c31\u662f\u8bf4\u6b64\u4e8b\u4ef6\u88ab\u5e7f\u64ad\u65f6\uff0c\u5b83\u5c06\u4f1a\u88ab\u5e7f\u64ad\u5230\u540d\u5b57\u4e3a orderStatus \u7684\u9891\u9053\u3002\n\u8fd9\u662f\u4e00\u4e2a\u300c\u516c\u6709\u9891\u9053\u300d\uff0c\u4efb\u4f55\u4eba\u53ef\u4ee5\u76d1\u542c\u6b64\u9891\u9053\uff0c\u5e76\u6536\u5230\u5e7f\u64ad\u7684\u6d88\u606f\u3002Laravel \u540c\u65f6\u63d0\u4f9b\u4e86\u300c\u79c1\u6709\u9891\u9053\u300d\uff0c\u7ecf\u8fc7\u6743\u9650\u9a8c\u8bc1\u540e\u624d\u80fd\u6210\u529f\u76d1\u542c\u3002\u6211\u4eec\u540e\u9762\u518d\u8bb2\u3002\n(6) \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cLaravel \u4f1a\u5c06\u300c\u4e8b\u4ef6\u540d\u300d\u4f5c\u4e3a\u5e7f\u64ad\u7684\u300c\u6d88\u606f\u540d\u300d\uff0c\u4e14\u4e0d\u5e26\u4efb\u4f55\u6570\u636e\u3002\u6211\u4eec\u53ef\u4ee5\u5728\u4e8b\u4ef6\u7c7b\u5185\u6dfb\u52a0\u4efb\u610f\u6210\u5458\u53d8\u91cf\uff0c\u5e76\u4fee\u6539\u6784\u9020\u51fd\u6570\uff0c\u4ee5\u5b9e\u73b0\u5c06\u6570\u636e\u53d1\u9001\u7ed9\u5ba2\u6237\u7aef\u3002\n\/\/\u53ef\u6dfb\u52a0\u4efb\u610f\u6210\u5458\u53d8\u91cf public $id; \/\/\u4e8b\u4ef6\u6784\u9020\u51fd\u6570 public function __construct($id) { $this-&gt;id = $id; } \/\/\u81ea\u5b9a\u4e49\u5e7f\u64ad\u7684\u6d88\u606f\u540d public function broadcastAs() { return &#39;anyName&#39;; } (5) \u5982\u4e0a\uff0c\u6211\u4eec\u5df2\u7ecf\u57fa\u672c\u5efa\u7acb\u8d77\u5e7f\u64ad\u7684\u57fa\u672c\u673a\u5236\u3002\u63a5\u4e0b\u6765\u6211\u4eec\u9700\u8981\u4e00\u4e2a\u80fd\u300c\u89e6\u53d1\u4e8b\u4ef6\u300d\uff08\u5373\u53d1\u9001\u5e7f\u64ad\uff09\u7684\u63a5\u53e3\u3002\n\u5728routes\/api.php\u6dfb\u52a0\u5982\u4e0b\u4ee3\u7801\uff1a\nRoute::get(&#39;\/ship&#39;, function (Request $request) { $id = $request-&gt;input(&#39;id&#39;); event(new OrderShipped($id)); \/\/ \u89e6\u53d1\u4e8b\u4ef6  return Response::make(&#39;Order Shipped!&#39;); }); (6) \u597d\u4e86\uff01\u6253\u5f00 Postman\uff0c\u8f93\u5165\uff1ahttp:\/\/***\/api\/ship?id=1000\uff0c\u53d1\u9001\u3002\n\u6253\u5f00storage\/logs\/laravel.log\uff0c\u4f60\u4f1a\u53d1\u73b0\u591a\u4e86\u51e0\u884c\uff1a\n[2018-03-02 01:41:19] local.INFO: Broadcasting [App\\Events\\OrderShipped] on channels [orderStatus] with payload: { &quot;id&quot;: &quot;1000&quot;, &quot;socket&quot;: null } \u606d\u559c\uff0c\u4f60\u5df2\u7ecf\u6210\u529f\u5730\u914d\u7f6e\u597d Broadcast \u7684 log Driver\u3002\n0x02 \u5e7f\u64ad \u5728\u4e0a\u4e00\u8282\uff0c\u6211\u4eec\u91c7\u7528log\u4f5c\u4e3a Broadcast Driver\uff0c\u4e5f\u5c31\u662f\u8bf4\u5e7f\u64ad\u7684\u6d88\u606f\u4f1a\u88ab\u8bb0\u5f55\u5230\u65e5\u5fd7\u5185\uff0c\u90a3\u4e48\u5982\u4f55\u771f\u6b63\u5730\u4e0e\u5ba2\u6237\u7aef\u8fdb\u884c\u901a\u4fe1\u5462\uff1f\u8fd9\u5c31\u9700\u8981\u7528\u5230\u6700\u5f00\u59cb\u63d0\u5230\u7684\u300c\u95f4\u63a5\u5c42\u300d\u4e86\u3002\n(1) \u9996\u5148\uff0c\u5c06 Driver \u7531log\u4fee\u6539\u4e3apusher\u3002\n \u4e3a\u4e86\u8282\u7701\u5b89\u88c5 Redis \u7684\u6b65\u9aa4\uff0c\u6211\u4eec\u5c06\u91c7\u7528 HTTP \u534f\u8bae\u76f4\u63a8\u81f3\u517c\u5bb9\u7684\u300c\u672c\u5730 Pusher \u670d\u52a1\u5668\u300d\uff08\u5373\u95f4\u63a5\u5c42\uff09\u3002\n (2) \u7531\u4e8e Laravel \u5185\u7f6e\u5e76\u6ca1\u6709\u643a\u5e26 Broadcast Pusher Driver\uff0c\u56e0\u6b64\u9700\u8981\u4f7f\u7528 Composer \u5b89\u88c5 Pusher PHP SDK\uff1a\ncomposer require pusher\/pusher-php-server (3) \u6ce8\u518cApp\\Providers\\BroadcastServiceProvider\u3002\n\u5bf9\u4e8e Laravel 5.6\uff0c\u53ea\u9700\u8981\u53d6\u6d88config\/app.php\u5185providers\u6570\u7ec4\u4e2d\u7684\u5bf9\u5e94\u6ce8\u91ca\u5373\u53ef\u3002\n(4) \u63a5\u4e0b\u6765\uff0c\u9700\u8981\u5b89\u88c5\u5e76\u914d\u7f6e\u670d\u52a1\u5668\u4e0e\u5ba2\u6237\u7aef\u901a\u4fe1\u7684\u300c\u95f4\u63a5\u5c42\u300d\u3002\n\u6211\u4eec\u91c7\u7528\u5b98\u65b9\u6587\u6863\u63a8\u8350\u7684\uff1atlaverdure\/laravel-echo-server\u3002\u8fd9\u662f\u4e00\u4e2a\u4f7f\u7528 Node.js + Socket.IO \u5b9e\u73b0\u7684 WebSocket \u670d\u52a1\u7aef\u3002\n \u5b83\u517c\u5bb9 Pusher HTTP API\uff0c\u6240\u4ee5\u5982\u4e0a\u80fd\u591f\u76f4\u63a5\u5c06 Driver \u4fee\u6539\u4e3a Pusher\uff0c\u800c\u4e0d\u662f Redis\u3002\n npm install -g laravel-echo-server \u521d\u59cb\u5316\u914d\u7f6e\u6587\u4ef6\uff0c\u6309\u7167\u63d0\u793a\u586b\u5199\u5373\u53ef\u3002\nlaravel-echo-server init\n\u6253\u5f00laravel-echo-server.json\uff0c\u68c0\u67e5\u90e8\u5206\u5173\u952e\u914d\u7f6e\u9879\u662f\u5426\u6b63\u786e\uff1a\n&#34;authHost&#34;: &#34;http:\/\/your.host&#34; \/\/ \u786e\u4fdd\u80fd\u591f\u8bbf\u95ee\u5230\u4f60\u7684 Laravel \u9879\u76ee &#34;port&#34;: &#34;6001&#34; \/\/ \u5efa\u8bae\u4e0d\u4f5c\u4fee\u6539\uff0c\u8fd9\u662f\u4e0e\u5ba2\u6237\u7aef\u901a\u4fe1\u7684\u7aef\u53e3 &#34;protocol&#34;: &#34;http&#34; \/\/ \u4e0e\u5ba2\u6237\u7aef\u901a\u4fe1\u7684\u534f\u8bae\uff0c\u652f\u6301 HTTPS \u590d\u5236\u4e24\u4e2a\u503c\uff1aclients.appId\u4ee5\u53caclients.key\uff0c\u5e76\u4fee\u6539config\/broadcasting.php\u3002\n&#39;pusher&#39; =&gt; [ &#39;driver&#39; =&gt; &#39;pusher&#39;, &#39;key&#39; =&gt; env(&#39;PUSHER_APP_KEY&#39;), &#39;secret&#39; =&gt; null, &#39;app_id&#39; =&gt; env(&#39;PUSHER_APP_ID&#39;), &#39;options&#39; =&gt; [ &#39;host&#39; =&gt; &#39;localhost&#39;, &#39;port&#39; =&gt; 6001, ], ], \u987e\u540d\u601d\u4e49\uff0c\u5c06appId\u548ckey\u5206\u522b\u586b\u5165\u76f8\u5e94\u914d\u7f6e\u9879\u6216\u4fee\u6539.env\u6587\u4ef6\u5373\u53ef\u3002\n\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u4fbf\u53ef\u4ee5\u4f7f\u7528\u547d\u4ee4laravel-echo-server start\u6765\u542f\u52a8\u670d\u52a1\u5668\uff0c\u76d1\u542c\u6765\u81ea Laravel \u7684\u300c\u5e7f\u64ad\u300d\u8bf7\u6c42\u3001\u4ee5\u53ca\u6765\u81ea\u5ba2\u6237\u7aef\u7684\u300c\u6536\u542c\u300d\u8bf7\u6c42\uff0c\u5e76\u8f6c\u53d1\u76f8\u5e94\u5e7f\u64ad\u6d88\u606f\u3002\n(5) \u4ece\u8fd9\u91cc\u5f00\u59cb\u6211\u4eec\u5c06\u4f1a\u914d\u7f6e\u524d\u7aef\u90e8\u5206\u3002\n\u9996\u5148\uff0c\u9700\u8981\u914d\u7f6e CSRF Token\u3002\n\u5982\u679c\u4f60\u4f7f\u7528 Blade \u6a21\u677f\u5f15\u64ce\uff0c\u5219\u6267\u884c php artisan make:auth \u547d\u4ee4\u5373\u53ef\u5c06 Token \u52a0\u5165 resources\/views\/layouts\/app.blade.php\u3002\n\u82e5\u6ca1\u6709\u4f7f\u7528\u6b64\u6a21\u677f\u6587\u4ef6\uff0c\u5219\u53ef\u4ee5\u76f4\u63a5\u5728 Blade \u6a21\u677f\u6587\u4ef6\u9996\u884c\u76f4\u63a5\u5199\u5165 Meta \u503c\u3002\n\u4e3a\u4e86\u4fbf\u4e8e\u6d4b\u8bd5\uff0c\u6211\u4eec\u5728 resources\/views\/welcome.blade.php \u5185\u6dfb\u52a0\uff1a\n&lt;meta name=&#34;csrf-token&#34; content=&#34;{{ csrf_token() }}&#34;&gt; \u5bf9\u4e8e\u524d\u540e\u7aef\u5206\u79bb\u7684\u9879\u76ee\uff0c\u53ef\u5173\u95ed CSRF Token \u9a8c\u8bc1\u3002\n(6) \u5176\u6b21\uff0c\u4f60\u9700\u8981\u5f15\u7528 Socket.IO \u7684\u5ba2\u6237\u7aef JS \u6587\u4ef6\uff0c\u4f4d\u7f6e\u540c\u4e0a\u3002\n&lt;script src=&#34;\/\/{{ Request::getHost() }}:6001\/socket.io\/socket.io.js&#34;&gt;&lt;\/script&gt; (7) \u8fd9\u91cc\u6211\u4eec\u91c7\u7528\u5b98\u65b9\u7684 Laravel Echo \u6269\u5c55\u5305\u6536\u542c\u670d\u52a1\u7aef\u5e7f\u64ad\u3002\u6253\u5f00resources\/assets\/js\/bootstrap.js\uff0c\u4fee\u6539\u6700\u540e\u51e0\u884c\u5373\u53ef\u3002\nimport Echo from &#39;laravel-echo&#39; window.Echo = new Echo({ broadcaster: &#39;socket.io&#39;, host: window.location.hostname + &#39;:6001&#39; }); \u63a5\u7740\u7f16\u5199\u300c\u6536\u542c\u9891\u9053\u300d\u4ee3\u7801\uff0c\u975e\u5e38\u7b80\u5355\uff1a\nwindow.Echo.channel(`orderStatus`) \/\/ \u5e7f\u64ad\u9891\u9053\u540d\u79f0  .listen(&#39;OrderShipped&#39;, (e) =&gt; { \/\/ \u6d88\u606f\u540d\u79f0  console.log(e); \/\/ \u6536\u5230\u6d88\u606f\u8fdb\u884c\u7684\u64cd\u4f5c\uff0c\u53c2\u6570 e \u4e3a\u6240\u643a\u5e26\u7684\u6570\u636e  }); (8) \u5b89\u88c5\u4f9d\u8d56\uff0c\u7f16\u8bd1\u524d\u7aef\u6587\u4ef6\u3002\u6267\u884c\u5982\u4e0b\u547d\u4ee4\uff1a\nnpm install npm install --save laravel-echo npm run dev \u6700\u540e\uff0c\u5728 Blade \u6a21\u677f\u5185\u5f15\u7528\u6211\u4eec\u521a\u521a\u5199\u597d\u7684 JS \u811a\u672c\u3002\u7531\u4e8eapp.js\u9ed8\u8ba4\u5df2\u7ecf\u5f15\u7528bootstrap.js\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u9700\u8981\u5f15\u7528app.js\u5373\u53ef\u3002\n\u6211\u4eec\u5728\u7b2c (5)\u6b65\u7684\u6587\u4ef6\u5185\u6dfb\u52a0\uff1a\n&lt;script src=&#34;{{ asset(&#39;\/js\/app.js&#39;) }}&#34;&gt;&lt;\/script&gt; (9) \u597d\u4e86\uff01\u5728\u67e5\u770b\u6548\u679c\u524d\uff0c\u4e0d\u8981\u5fd8\u8bb0\u6267\u884c\u7b2c (4)\u6b65\u7684\u6700\u540e\u4e00\u6761\u547d\u4ee4\uff0c\u542f\u52a8 Laravel Echo Server\u3002\nLaravel \u9ed8\u8ba4\u5df2\u7ecf\u5b9a\u4e49\u9996\u9875\u8def\u7531\u6e32\u67d3welcome.blade.php\u6a21\u677f\uff0c\u73b0\u5728\u53ea\u8981\u4f7f\u7528\u6d4f\u89c8\u5668\u8bbf\u95ee\u5e94\u7528 URL \u5373\u53ef\u3002\n\u5982\u679c\u67e5\u770b Chrome \u63a7\u5236\u53f0\uff0c\u6ca1\u6709\u4efb\u4f55\u9519\u8bef\u4ea7\u751f\uff1b\u67e5\u770b\u547d\u4ee4\u884c\u7a97\u53e3\uff0c\u6ca1\u6709\u9519\u8bef\u8f93\u51fa\uff1b\u5219\u8bf4\u660e\u5ba2\u6237\u7aef\u4e0e\u670d\u52a1\u5668\u4f3c\u4e4e\u5df2\u7ecf\u6b63\u5e38\u5efa\u7acb WebSocket \u8fde\u63a5\u3002\n\u8fd9\u65f6\uff0c\u4f60\u53ef\u4ee5\u91cd\u65b0\u6253\u5f00 Postman\uff0c\u53d1\u9001\u4e0a\u4e00\u8282\u4e2d\u7684\u8bf7\u6c42\u3002\n\u518d\u6b21\u67e5\u770b\u5982\u4e0a\u4e24\u4e2a\u7a97\u53e3\uff0c\u4f1a\u6709\u60ca\u559c\u54df\u3002\n0x03 \u79c1\u6709\u9891\u9053 \u4e0a\u4e00\u8282\u6211\u4eec\u6210\u529f\u5b9e\u73b0\u53ef\u4ee5\u88ab\u4efb\u4f55\u4eba\u6536\u542c\u7684\u300c\u5171\u6709\u9891\u9053\u300d\u5e7f\u64ad\uff0c\u90a3\u4e48\u5982\u4f55\u4e0e\u90e8\u5206\u5ba2\u6237\u7aef\u8fdb\u884c\u901a\u8baf\u5462\uff1f\u4ec5\u4ec5\u4f9d\u9760\u524d\u7aef\u7684\u9a8c\u8bc1\u662f\u4e0d\u591f\u7684\u3002\u6211\u4eec\u9700\u8981\u521b\u5efa\u5e26\u6709\u300c\u8ba4\u8bc1\u300d\u529f\u80fd\u7684\u300c\u79c1\u6709\u9891\u9053\u300d\u3002\n(1) \u9996\u5148\uff0c\u6253\u5f00 app\/Providers\/BroadcastServiceProvider.php\uff0c\u5728\u4e0a\u4e00\u8282\u4e2d\u6211\u4eec\u5df2\u7ecf\u6ce8\u518c\u6b64\u670d\u52a1\u63d0\u4f9b\u8005\uff0c\u73b0\u5728\u6211\u4eec\u9700\u8981\u53d6\u6d88\u6ce8\u91ca\u4e00\u90e8\u5206\u4ee3\u7801\u3002\npublic function boot() { Broadcast::routes(); \/\/ \u8fd8\u8bb0\u5f97 laravel-echo-server.json \u7684 authEndpoint \u914d\u7f6e\u9879\u5417\uff1f \trequire base_path(&#39;routes\/channels.php&#39;); } Broadcast::routes() \u7528\u4e8e\u6ce8\u518c\u9a8c\u8bc1\u8def\u7531\uff08\u5373 \/broadcasting\/auth\uff09\uff0c\u5f53\u5ba2\u6237\u7aef\u6536\u542c\u9891\u9053\u65f6\uff0cLaravel Echo Server \u4f1a\u8bbf\u95ee\u6b64\u8def\u7531\uff0c\u4ee5\u9a8c\u8bc1\u5ba2\u6237\u7aef\u662f\u5426\u7b26\u5408\u300c\u8ba4\u8bc1\u300d\u6761\u4ef6\u3002\n(2) Broadcast \u8ba4\u8bc1\u5206\u4e3a\u4e24\u4e2a\u90e8\u5206\uff1a\n \u4f7f\u7528 Laravel \u5185\u7f6e\u7684 Auth \u7cfb\u7edf\u8fdb\u884c\u8ba4\u8bc1\u3002 \u6839\u636e\u81ea\u5b9a\u4e49\u89c4\u5219\u8fdb\u884c\u90e8\u5206\u9891\u9053\u7684\u8ba4\u8bc1\u3002  (3) \u9996\u5148\uff0c\u9700\u8981\u914d\u7f6e Auth \u8ba4\u8bc1\u7cfb\u7edf\u3002\n\u6839\u636e\u60c5\u51b5\u4fee\u6539 .env \u6587\u4ef6\u7684\u6570\u636e\u5e93\u914d\u7f6e\u9879\u540e\uff0c\u53ea\u9700\u8981\u6267\u884c php artisan make:auth \u521b\u5efa\u6240\u9700\u6587\u4ef6\uff0c\u518d\u6267\u884c php artisan migrate \u521b\u5efa\u6240\u9700\u6570\u636e\u5e93\u7ed3\u6784\u5373\u53ef\u3002\n \u6df1\u5165\u4e86\u89e3\uff0c\u8bf7\u53c2\u8003 \u7528\u6237\u8ba4\u8bc1 \u6587\u6863\u3002\n \u63a5\u4e0b\u6765\u6211\u4eec\u5728\u6d4f\u89c8\u5668\u4e2d\u6253\u5f00\u4f60\u7684\u5e94\u7528\uff0c\u4f1a\u53d1\u73b0\u53f3\u4e0a\u89d2\u591a\u4e86\u767b\u5f55\u548c\u6ce8\u518c\uff0c\u6211\u4eec\u968f\u610f\u6ce8\u518c\u4e00\u4e2a\u6d4b\u8bd5\u7528\u6237\u4ee5\u5907\u4f7f\u7528\u3002\n(4) \u63a5\u4e0b\u6765\uff0c\u914d\u7f6e\u9891\u9053\u8ba4\u8bc1\u3002\n\u8fd8\u8bb0\u5f97\u7b2c (1) \u6b65\u7684 routes\/channels.php \u5417\uff0c\u6211\u4eec\u6253\u5f00\u6b64\u6587\u4ef6\u3002\u5e76\u65b0\u589e\u4e00\u6761\u9891\u9053\u8ba4\u8bc1\u89c4\u5219\u3002\n \u6ce8\u610f\uff1a\u867d\u7136\u6b64\u6587\u4ef6\u4f4d\u4e8e routes \u76ee\u5f55\u4e0b\uff0c\u4f46\u5e76\u4e0d\u662f\u8def\u7531\u6587\u4ef6\uff01\u5728\u6b64\u5b9a\u4e49\u540e\u5e76\u4e0d\u80fd\u8bbf\u95ee\uff0c\u4e14\u65e0\u6cd5\u4f7f\u7528\u5206\u7ec4\u3001\u4e2d\u95f4\u4ef6\u3002\u6240\u6709\u7684\u9a8c\u8bc1\u8def\u7531\u90fd\u5df2\u7ecf\u5728 Broadcast::routes() \u4e2d\u5b9a\u4e49\u3002\n Broadcast::channel(&#39;orderStatus&#39;, function ($user, $value) { return true; \/\/ or false }); \u7531\u4e8e Broadcast \u5df2\u7ecf\u4f7f\u7528 Auth \u8fdb\u884c\u7528\u6237\u767b\u5f55\u8ba4\u8bc1\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u9700\u65e0\u6761\u4ef6\u8fd4\u56de true \u5373\u53ef\u5b9e\u73b0\uff1a\u4efb\u4f55\u5df2\u767b\u5f55\u7528\u6237\u90fd\u53ef\u4ee5\u6536\u542c\u6b64\u9891\u9053\u3002\n(5) \u8ba4\u8bc1\u90e8\u5206\u6211\u4eec\u5df2\u7ecf\u914d\u7f6e\u5b8c\u6210\uff0c\u63a5\u4e0b\u6765\u5c06\u5171\u6709\u9891\u9053\u7684\u5b9a\u4e49\u6539\u4e3a\u79c1\u6709\u3002\n\u4fee\u6539\u5e7f\u64ad\u6d88\u606f\u57fa\u4e8e\u7684\u4e8b\u4ef6\u7c7b app\/Events\/OrderShipped.php\uff1a\npublic function broadcastOn() { return new PrivateChannel(&#39;orderStatus&#39;); \/\/ \u79c1\u6709\u9891\u9053 } \u4fee\u6539\u5ba2\u6237\u7aef\u6536\u542c\u4ee3\u7801 resources\/assets\/js\/bootstrap.js\u3002\nwindow.Echo.private(`orderStatus`) \/\/ \u79c1\u6709\u9891\u9053  .listen(&#39;OrderShipped&#39;, (e) =&gt; { console.log(e); }); (6) \u63a5\u4e0b\u6765\uff0c\u518d\u6b21\u8fd0\u884c Laravel Echo Server\u3002\u4f7f\u7528\u6d4f\u89c8\u5668\u6253\u5f00\u4f60\u7684\u5e94\u7528\u9996\u9875\uff0c\u5728\u672a\u767b\u5f55\u72b6\u6001\uff0c\u53ef\u4ee5\u770b\u5230 Echo Server \u8f93\u51fa\u4e00\u4e2a\u6765\u81ea Laravel \u7684 AccessDeniedHttpException \u5f02\u5e38\uff0c\u63d0\u793a\u7528\u6237\u8ba4\u8bc1\u5931\u8d25\uff0c\u65e0\u6cd5\u6536\u542c\u9891\u9053\u3002\n\u767b\u5f55\u540e\uff0c\u5373\u53ef\u83b7\u5f97\u4e0e\u4e0a\u4e00\u8282\u76f8\u540c\u7684\u9884\u671f\u7ed3\u679c\u3002\n(7) \u5982\u4e0a\uff0c\u6211\u4eec\u6210\u529f\u5b9e\u73b0\u6240\u6709\u767b\u5f55\u7528\u6237\u5747\u53ef\u6536\u542c\u79c1\u6709\u9891\u9053\u3002\u90a3\u4e48\u5982\u4f55\u5b9e\u73b0\u67d0\u90e8\u5206\u7528\u6237\u53ef\u4ee5\u6536\u542c\uff0c\u67d0\u90e8\u5206\u7528\u6237\u4e0d\u53ef\u4ee5\u6536\u542c\u9891\u9053\uff1f\u4f8b\u5982\uff1a\u67d0\u4e2a\u7528\u6237\u5747\u6709\u5c5e\u4e8e\u81ea\u5df1\u7684\u9891\u9053\uff0c\u4ed6\u53ea\u80fd\u6536\u542c\u81ea\u5df1\u7684\u9891\u9053\u3002\u8bf7\u7ee7\u7eed\u5f80\u4e0b\u770b\u3002\n\u9996\u5148\uff0c\u4fee\u6539\u5e7f\u64ad\u6d88\u606f\u57fa\u4e8e\u7684\u4e8b\u4ef6\u7c7b app\/Events\/OrderShipped.php\u3002\u4f60\u9700\u8981\u5c06\u9891\u9053\u547d\u540d\u4fee\u6539\u4e3a\u52a8\u6001\u7684\u503c\u3002\npublic $userId; \/\/ \u65b0\u589e\u6210\u5458\u53d8\u91cf userId\uff0c\u4e0d\u8981\u5fd8\u8bb0\u5728\u6784\u9020\u51fd\u6570\u5185\u5bf9\u5176\u8fdb\u884c\u8d4b\u503c  public function broadcastOn() { return new PrivateChannel(&#39;orderStatus-&#39; . $this-&gt;userId); \/\/ \u52a8\u6001\u547d\u540d\u79c1\u6709\u9891\u9053 } \u5176\u6b21\uff0c\u4fee\u6539\u7b2c (4) \u6b65\u4e2d\u7684 routes\/channels.php \u6587\u4ef6\u3002Broadcast \u652f\u6301\u4f7f\u7528\u901a\u914d\u7b26\u5339\u914d\u300c\u67d0\u4e00\u7c7b\u300d\u9891\u9053\u8fdb\u884c\u9a8c\u8bc1\u3002\nBroadcast::channel(&#39;orderStatus-{userId}&#39;, function ($user, $value) { \/\/ $user\tAuth\u8ba4\u8bc1\u901a\u8fc7\u7684\u7528\u6237\u6a21\u578b\u5b9e\u4f8b  \/\/ $value\t\u9891\u9053\u89c4\u5219\u5339\u914d\u5230\u7684 userId \u503c  return $user-&gt;id == $value; \/\/ \u53ef\u4f7f\u7528\u4efb\u610f\u6761\u4ef6\u9a8c\u8bc1\u6b64\u7528\u6237\u662f\u5426\u53ef\u76d1\u542c\u6b64\u9891\u9053 }); \u6700\u540e\u522b\u5fd8\u8bb0\u4fee\u6539\u524d\u7aef\u6536\u542c\u7684\u9891\u9053\u540d\u79f0\u3002\n\u518d\u6b21\u6253\u5f00\u6d4f\u89c8\u5668\u6d4b\u8bd5\u5373\u53ef\u53d1\u73b0\uff1a\u5728\u672c\u4f8b\u4e2d\uff0c\u82e5\u5ba2\u6237\u7aef\u6536\u542c\u7684\u9891\u9053\u4e0d\u5339\u914d\u5f53\u524d\u7528\u6237 ID\uff0c\u5219\u4f1a\u62a5\u9519\u3002\n(8) \u5982\u4e0a\uff0c\u6211\u4eec\u6210\u529f\u5b9e\u73b0\u5bf9\u79c1\u6709\u9891\u9053\u8fdb\u884c\u81ea\u5b9a\u4e49\u89c4\u5219\u7684\u8ba4\u8bc1\uff1b\u4f46\u5982\u679c\u6211\u4eec\u6ca1\u6709\u4f7f\u7528 Auth \u8ba4\u8bc1\u7cfb\u7edf\uff0c\u6216\u91c7\u7528\u4e86\u81ea\u5df1\u7f16\u5199\u7684\u7528\u6237\u8ba4\u8bc1\u4e2d\u95f4\u4ef6\uff0c\u8be5\u5982\u4f55\u517c\u5bb9\u5462\uff1f\n\u7ecf\u8fc7\u4e00\u756a\u6e90\u7801\u8c03\u8bd5\uff0c\u6211\u53d1\u73b0 Broadcast \u5728 vendor\/laravel\/framework\/src\/Illuminate\/Broadcasting\/Broadcasters\/ \u6587\u4ef6\u5939\u4e0b\u5b9a\u4e49\u7684 Broadcaster \u5185\u8c03\u7528 $request-&gt;user() \u8fdb\u884c\u4e86\u7528\u6237\u9a8c\u8bc1\u3002\n\u4f8b\u5982\u6211\u4eec\u91c7\u7528\u7684 PusherBroadcaster.php\uff1a\n\/** * Authenticate the incoming request for a given channel. * * @param \\Illuminate\\Http\\Request $request * @return mixed * @throws \\Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException *\/ public function auth($request) { if (Str::startsWith($request-&gt;channel_name, [&#39;private-&#39;, &#39;presence-&#39;]) &amp;&amp; ! $request-&gt;user()) { throw new AccessDeniedHttpException; } $channelName = Str::startsWith($request-&gt;channel_name, &#39;private-&#39;) ? Str::replaceFirst(&#39;private-&#39;, &#39;&#39;, $request-&gt;channel_name) : Str::replaceFirst(&#39;presence-&#39;, &#39;&#39;, $request-&gt;channel_name); return parent::verifyUserCanAccessChannel( $request, $channelName ); } \u7531\u6b64\u53ef\u5f97\uff0c\u6211\u4eec\u6709\u4e24\u79cd\u65b9\u5f0f\u5b9e\u73b0\u3002\n\u7b2c\u4e00\u79cd \u76f4\u63a5\u6ce8\u91ca throw new AccessDeniedHttpException\uff0c\u5e76\u4fee\u6539 app\/Providers\/BroadcastServiceProvider.php\u3002\nBroadcast::routes() \u53ef\u63a5\u6536\u4e00\u4e2a\u53c2\u6570\u3002\u5728 vendor\/laravel\/framework\/src\/Illuminate\/Broadcasting\/BroadcastManager.php \u53ef\u67e5\u770b\u5176\u5b9a\u4e49\uff1a\n\/** * Register the routes for handling broadcast authentication and sockets. * * @param array|null $attributes * @return void *\/ public function routes(array $attributes = null) { if ($this-&gt;app-&gt;routesAreCached()) { return; } $attributes = $attributes ?: [&#39;middleware&#39; =&gt; [&#39;web&#39;]]; $this-&gt;app[&#39;router&#39;]-&gt;group($attributes, function ($router) { $router-&gt;post(&#39;\/broadcasting\/auth&#39;, &#39;\\\\&#39;.BroadcastController::class.&#39;@authenticate&#39;); }); } \u901a\u8fc7\u6e90\u7801\u53ef\u77e5\uff1a\u6b64\u53c2\u6570\u7b49\u6548\u4e8e Route::group() \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\u6240\u4ee5\u6211\u4eec\u53ea\u8981\u5c06\u5176\u4fee\u6539\u4e3a\u5982\u4e0b\u5f62\u5f0f\uff1a\nBroadcast::routes([&#39;middleware&#39; =&gt; [&#39;yourMiddleware&#39;]) \u5e76\u5728\u4e2d\u95f4\u4ef6\u5185\u8fdb\u884c\u7528\u6237\u8ba4\u8bc1\uff1b\u5982\u672a\u767b\u5f55\uff0c\u7167\u5e38\u629b\u51fa AccessDeniedHttpException \u5f02\u5e38\u5373\u53ef\u3002\n\u7b2c\u4e8c\u79cd \u5728vendor\/laravel\/framework\/src\/Illuminate\/Http\/Request.php \u53ef\u4ee5\u67e5\u770b\u5230 $request-&gt;user() \u7684\u5b9a\u4e49\u3002\n\/** * Get the user making the request. * * @param string|null $guard * @return mixed *\/ public function user($guard = null) { return call_user_func($this-&gt;getUserResolver(), $guard); } \u5982\u4e0a\u53ef\u77e5\uff0c\u5b83\u4f7f\u7528 $this-&gt;userResolver \u5185\u7684\u533f\u540d\u51fd\u6570\u83b7\u53d6\u7528\u6237\u6a21\u578b\u3002\u6240\u4ee5\u6211\u4eec\u53ea\u9700\u8981\u5728 AuthServiceProvider \u6ce8\u518c\u540e\uff0cBroadcast \u8ba4\u8bc1\u524d\uff0c\u66ff\u6362\u6389\u5176 userResolver \u5373\u53ef\u3002\n\u4f8b\u5982\uff1a\u7ee7\u627f Illuminate\\Auth\\AuthServiceProvider\uff08vendor\/laravel\/framework\/src\/Illuminate\/Auth\/AuthServiceProvider.php\uff09\uff0c\u5e76\u91cd\u5199 registerRequestRebindHandler \u65b9\u6cd5\u53ca\u6784\u9020\u51fd\u6570\uff0c\u6dfb\u52a0\u5982\u4e0b\u4ee3\u7801\u3002\n$request-&gt;setUserResolver(function ($guard = null) use ($app) { \/\/ \u5728\u6b64\u5224\u65ad\u7528\u6237\u767b\u5f55\u72b6\u6001  \/\/ \u82e5\u767b\u5f55\uff0c\u8bf7\u8fd4\u56de App\\User \u6216\u5176\u5b83\u7528\u6237\u6a21\u578b\u5b9e\u4f8b  \/\/ \u672a\u767b\u5f55\uff0c\u8bf7\u8fd4\u56de null }); \u4fee\u6539 config\/app.php\uff0c\u4f7f\u7528\u6539\u9020\u8fc7\u7684 AuthServiceProvider \u7c7b\u66ff\u6362\u539f\u670d\u52a1\u63d0\u4f9b\u8005\u5373\u53ef\u3002\n0x04 \u6269\u5c55\u9605\u8bfb   Laravel Broadcast\u2014\u2014\u5e7f\u64ad\u7cfb\u7edf\u6e90\u7801\u5256\u6790\n  Laravel \u4e2d\u670d\u52a1\u7aef\u4e0e\u5ba2\u6237\u7aef\u4e8b\u4ef6\u5e7f\u64ad\u5b9e\u73b0\n  0x05 \u603b\u7ed3 \u81f3\u6b64\uff0c\u4f60\u5df2\u7ecf\u5efa\u7acb\u5bf9 Laravel Boardcast \u7684\u57fa\u672c\u8ba4\u8bc6\uff0c\u6210\u529f\u5165\u95e8\u300c\u5e7f\u64ad\u7cfb\u7edf\u300d\u3002\n\u53e6\u5916\uff0cLaravel 5.6 \u65b0\u589e\u4e00\u6761\u5173\u4e8e Broadcast \u7684\u65b0\u7279\u6027\uff0c\u907f\u514d\u5728 routes\/channels.php \u6587\u4ef6\u5185\u7f16\u5199\u4f17\u591a\u95ed\u5305\u5bfc\u81f4\u7684\u96be\u4ee5\u7ef4\u62a4\u3002\u8be6\u60c5\u53ef\u67e5\u770b\uff1aLaravel 5.6 \u65b0\u7248\u7279\u6027\u3002\n\u5176\u5b9e\uff0c\u672c\u6587\u53ea\u4e0d\u8fc7\u629b\u7816\u5f15\u7389\u800c\u5df2\u3002\u5bf9\u4e8e\u90e8\u7f72\u5230\u751f\u4ea7\u73af\u5883\uff0c\u4ecd\u7136\u5b58\u5728\u8bb8\u591a\u95ee\u9898\uff0c\u4f8b\u5982\uff1a\n \u4e0e\u5e38\u89c1 PHP \u5e94\u7528\u4e0d\u540c\uff0c\u5e7f\u64ad\u57fa\u4e8e WebSocket \u957f\u8fde\u63a5\uff1b\u90a3\u4e48\u5982\u4f55\u786e\u4fdd\u901a\u4fe1\u7a33\u5b9a\u6027\uff0c\u5982\u4f55\u5254\u9664\u6b7b\u94fe\uff1f \u4e3a\u4e86\u786e\u4fdd\u5e94\u7528\u8bbf\u95ee\u901f\u5ea6\uff0c\u5e7f\u64ad\u901a\u5e38\u662f\u5f02\u6b65\u6267\u884c\u7684\uff1b\u90a3\u4e48\u5982\u4f55\u914d\u7f6e\u4e8b\u4ef6\u961f\u5217\uff1f\u5982\u4f55\u5c06\u961f\u5217\u914d\u7f6e\u4e3a\u5f02\u6b65\uff1f \u5982\u4f55\u786e\u4fdd Laravel Echo Server \u8fdb\u7a0b\u7a33\u5b9a\u8fd0\u884c\uff1f\u5982\u4f55\u5904\u7406\u5f02\u5e38\uff1f\u662f\u5426\u9700\u8981\u5173\u95ed Debug \u6a21\u5f0f\uff1f \u5982\u4f55\u786e\u4fdd Laravel Echo \u4e0e\u670d\u52a1\u7aef\u8fde\u63a5\u7a33\u5b9a\uff1f\u662f\u5426\u9700\u8981\u5b9a\u65f6\u68c0\u67e5\uff1f\u5982\u4f55\u6355\u6349\u5e76\u5b8c\u5584\u5730\u5904\u7406\u6240\u6709\u5f02\u5e38\uff1f \u5ba2\u6237\u7aef\u6536\u542c\u79c1\u6709\u9891\u9053\uff0c\u82e5\u88ab\u670d\u52a1\u5668\u62d2\u7edd\uff0c\u662f\u5426\u9700\u8981\u65ad\u5f00\u8fde\u63a5\uff1f\u5982\u4f55\u7ed9\u4e88\u7528\u6237\u53cb\u597d\u5730\u63d0\u793a\uff1f \u2026\u2026  \u5f53\u7136\uff0c\u8fd9\u4e9b\u95ee\u9898\u672c\u6587\u6ca1\u6709\u63d0\u5230\uff0c\u4f46\u7f51\u7edc\u4e0a\u5df2\u7ecf\u6709\u65e0\u6570\u6210\u719f\u3001\u4fbf\u6377\u7684\u89e3\u51b3\u65b9\u6848\uff1b\u66f4\u591a\u9ad8\u7ea7\u7528\u6cd5\u4e5f\u53ef\u4ee5\u53c2\u7167\u672c\u6587\u6700\u521d\u5217\u51fa\u7684\u5b98\u65b9\u6587\u6863\u3002\n0xFF \u611f\u8a00 \u201c\u5728\u8ba1\u7b97\u673a\u9886\u57df\u5185\uff0c\u6ca1\u6709\u4ec0\u4e48\u662f\u52a0\u4e00\u4e2a\u4e2d\u95f4\u5c42\u89e3\u51b3\u4e0d\u6389\u7684\u95ee\u9898\uff1b\u5982\u679c\u6709\uff0c\u518d\u52a0\u4e00\u5c42\u3002\u201d\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-broadcasting\/","summary":"Laravel \u96c6\u6210\u4f17\u591a\u5f00\u5305\u5373\u7528\u7684\u529f\u80fd, \u867d\u7136\u5b83\u771f\u7684\u5f88&quot;\u80d6&quot;, \u4f46\u8fd9\u5e76\u4e0d\u5f71\u54cd\u5b83\u662f\u4e2a\u597d\u6846\u67b6. \u672c\u7bc7\u6587\u7ae0\u5c06\u91c7\u7528 Laravel 5.6 \u7248\u672c\u7531\u6d45\u5165\u6df1\u4e3a\u5927\u5bb6\u6f14\u793a: \u5982\u4f55\u4f7f\u7528\u5185\u7f6e\u7684 Broadcast\uff08\u5e7f\u64ad\uff09\u529f\u80fd\u5b9e\u73b0\u4e0e\u5ba2\u6237\u7aef\u5b9e\u65f6\u901a\u4fe1.\n Tips: \u6b64\u4ed3\u5e93\u5b9e\u73b0\u672c\u6587\u4e2d\u7684 0x02 \u5e7f\u64ad \u4ee3\u7801\u3002\n0x00 \u51c6\u5907  \u5e7f\u64ad\u7cfb\u7edf - Laravel 5.","title":"\u7531\u6d45\u5165\u6df1\uff1aLaravel Broadcast \u5b9e\u73b0 WebSocket B\/S \u5b9e\u65f6\u901a\u4fe1"},{"content":" \u6811\u8393\u6d3e\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u865a\u62df\u5185\u5b58\u53ea\u6709\u533a\u533a 100 MB\uff0c\u8fd9\u5b8c\u5168\u4e0d\u80fd\u6ee1\u8db3\u6b63\u5e38\u4f7f\u7528\u9700\u6c42\uff0c\u672c\u6587\u5c06\u8bb2\u89e3\u5982\u4f55\u4fee\u6539\u4e3a\u5408\u7406\u7684\u503c\u3002\n \u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u5728 Linux \u5185\uff0c\u6211\u4eec\u91c7\u7528swapoff\/mkswap\/swapon\u7b49\u547d\u4ee4\u6765\u683c\u5f0f\u5316\u5e76\u6302\u8f7d Swap\uff0c\u4f46\u5728\u6811\u8393\u6d3e\u5185\u6211\u4eec\u4e0d\u63a8\u8350\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\uff0c\u6811\u8393\u6d3e\u672c\u8eab\u63d0\u4f9b\u4e86\u914d\u7f6e\u6587\u4ef6\u53ef\u4ee5\u76f4\u63a5\u4fee\u6539\u3002\nsudo nano \/etc\/dphys-swapfile\n\u627e\u5230\u5982\u4e0b\u884c\uff1a\nCONF_SWAPSIZE=100\n\u4fee\u6539\u4e3a\uff1a\nCONF_SWAPSIZE=1024\n\u7136\u540e\u91cd\u542f\uff0c\u4f7f\u7528free -m\u67e5\u770b\uff0c\u4f60\u5c31\u4f1a\u53d1\u73b0\uff1a\n total used free shared buff\/cache available Mem: 875 103 492 19 279 702 Swap: 1023 0 1023 Swap \u5df2\u7ecf\u53d8\u4e3a 1GB\u3002\n Referer: http:\/\/www.bitpi.co\/2015\/02\/11\/how-to-change-raspberry-pis-swapfile-size-on-rasbian\/\n ","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-change-swap-size\/","summary":"\u6811\u8393\u6d3e\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u865a\u62df\u5185\u5b58\u53ea\u6709\u533a\u533a 100 MB\uff0c\u8fd9\u5b8c\u5168\u4e0d\u80fd\u6ee1\u8db3\u6b63\u5e38\u4f7f\u7528\u9700\u6c42\uff0c\u672c\u6587\u5c06\u8bb2\u89e3\u5982\u4f55\u4fee\u6539\u4e3a\u5408\u7406\u7684\u503c\u3002\n \u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u5728 Linux \u5185\uff0c\u6211\u4eec\u91c7\u7528swapoff\/mkswap\/swapon\u7b49\u547d\u4ee4\u6765\u683c\u5f0f\u5316\u5e76\u6302\u8f7d Swap\uff0c\u4f46\u5728\u6811\u8393\u6d3e\u5185\u6211\u4eec\u4e0d\u63a8\u8350\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\uff0c\u6811\u8393\u6d3e\u672c\u8eab\u63d0\u4f9b\u4e86\u914d\u7f6e\u6587\u4ef6\u53ef\u4ee5\u76f4\u63a5\u4fee\u6539\u3002\nsudo nano \/etc\/dphys-swapfile\n\u627e\u5230\u5982\u4e0b\u884c\uff1a\nCONF_SWAPSIZE=100\n\u4fee\u6539\u4e3a\uff1a\nCONF_SWAPSIZE=1024\n\u7136\u540e\u91cd\u542f\uff0c\u4f7f\u7528free -m\u67e5\u770b\uff0c\u4f60\u5c31\u4f1a\u53d1\u73b0\uff1a\n total used free shared buff\/cache available Mem: 875 103 492 19 279 702 Swap: 1023 0 1023 Swap \u5df2\u7ecf\u53d8\u4e3a 1GB\u3002","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0 - \u4fee\u6539 Swap \u5927\u5c0f"},{"content":" \u767e\u5ea6\u6765\u7684\u6559\u7a0b\u90fd\u662f\u6e90\u7801\u7f16\u8bd1\u5b89\u88c5\uff0c\u5bf9\u4e8e\u6211\u8fd9\u79cd\u5f3a\u8feb\u75c7\u4eba\u7fa4\u6765\u8bf4\u7b80\u76f4\u662f\u4e0d\u5f97\u5df2\u624d\u4f1a\u91c7\u7528\u7684\u65b9\u6848\uff0c\u4e8e\u662f\u679c\u65ad\u81ea\u5df1\u5c1d\u8bd5\u4f7f\u7528 apt-get \u5b89\u88c5 Nginx + PHP \u8fd0\u884c\u73af\u5883\u3002\n 0x00 Update apt.\nsudo apt-get update sudo apt-get upgrade 0x01 Install Nginx, PHP7.0, and PHP-FPM.\nsudo apt-get install nginx sudo apt-get install php7.0 php7.0-fpm Alternatively, you may also install PHP-CGI.\nsudo apt-get install php7.0-cgi 0x02 Configure Nginx.\nsudo nano \/etc\/nginx\/sites-available\/default  Note: \/etc\/nginx\/nginx.conf has already included all files in sites-enabled folder, so create another config file if you wanna setup a new vhost.\n Here we use PHP-FPM, so uncomment those lines:\nlocation ~ \\.php$ { include snippets\/fastcgi-php.conf; # With php-fpm (or other unix sockets): fastcgi_pass unix:\/var\/run\/php\/php7.0-fpm.sock; # With php-cgi (or other tcp sockets): #fastcgi_pass 127.0.0.1:9000; } And do NOT forget to reload Nginx.\nsudo nginx -s reload 0x03 Write some PHP codes to \/var\/www\/html\necho &quot;&lt;?php phpinfo(); ?&gt;&quot; &gt; \/var\/www\/html\/phpinfo.php And test it. Open your browser and type: http:\/\/&lt;YOUR_PI_IP&gt;\/phpinfo.php\nIt should return a response like this:\nEnjoy PHP in your Raspberry Pi!\n0x04 Here are some PHP projects that I found useful for your Pi. Hope you like it.\nKODExplorer\nPi Dashboard\n0x05 \u8fa3\u9e21\u767e\u5ea6.\n","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-installing-nginx-php-via-apt\/","summary":"\u767e\u5ea6\u6765\u7684\u6559\u7a0b\u90fd\u662f\u6e90\u7801\u7f16\u8bd1\u5b89\u88c5\uff0c\u5bf9\u4e8e\u6211\u8fd9\u79cd\u5f3a\u8feb\u75c7\u4eba\u7fa4\u6765\u8bf4\u7b80\u76f4\u662f\u4e0d\u5f97\u5df2\u624d\u4f1a\u91c7\u7528\u7684\u65b9\u6848\uff0c\u4e8e\u662f\u679c\u65ad\u81ea\u5df1\u5c1d\u8bd5\u4f7f\u7528 apt-get \u5b89\u88c5 Nginx + PHP \u8fd0\u884c\u73af\u5883\u3002\n 0x00 Update apt.\nsudo apt-get update sudo apt-get upgrade 0x01 Install Nginx, PHP7.","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0 - \u4f7f\u7528 apt-get \u5b89\u88c5 Nginx+PHP"},{"content":" \u7f51\u7edc\u4e0a\u6709\u4e0d\u5c11\u5b89\u88c5 Node.js \u548c\u7f16\u8bd1\u6e90\u7801\u5347\u7ea7\u7684\u6559\u7a0b\uff0c\u4f46\u5728\u6211\u624b\u4e0a\u7684\u6811\u8393\u6d3e\uff08\u7cfb\u7edf\u7248\u672c\uff1aNovember 2017\uff09\u5df2\u7ecf\u5185\u7f6e Node.js 4.x \u7248\u672c\u3002\u4e3a\u4e86\u4fdd\u6301\u7cfb\u7edf\u5e72\u51c0\u6574\u6d01\uff0c\u4e0d\u60f3\u4f7f\u7528\u6e90\u7801\u7f16\u8bd1\u6765\u66f4\u65b0\uff0c\u672c\u6587\u5c06\u8bb2\u89e3\u5982\u4f55\u64cd\u4f5c\u3002\n 0x00 \u5378\u8f7d \u5378\u8f7d\u539f\u6709 node.js \u4ee5\u53ca npm\u3002\nsudo apt-get remove nodejs npm sudo apt autoremove 0x01 \u5b89\u88c5 \u5b89\u88c5\u524d\uff0c\u6211\u4eec\u9700\u8981\u66f4\u65b0 apt \u6e90\u4e3a\u5305\u542b\u6307\u5b9a node.js \u7248\u672c\u7684\u6e90\uff1bnode \u5b98\u7f51\u6709\u6700\u65b0\u7684\u547d\u4ee4\u884c\uff0c\u53c2\u89c1\uff1a Installing Node.js via package manager\n\u622a\u6b62\u672c\u6587\u7f16\u5199\uff0cnode.js \u7a33\u5b9a\u7248\u672c\u4e3a 8.x\uff0c\u6240\u4ee5\u6211\u4eec\u6267\u884c\uff1a\ncurl -sL https:\/\/deb.nodesource.com\/setup_8.x | sudo -E bash - sudo apt-get install -y nodejs \u5b8c\u6210\uff01\n","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-upgrade-nodejs-via-apt\/","summary":"\u7f51\u7edc\u4e0a\u6709\u4e0d\u5c11\u5b89\u88c5 Node.js \u548c\u7f16\u8bd1\u6e90\u7801\u5347\u7ea7\u7684\u6559\u7a0b\uff0c\u4f46\u5728\u6211\u624b\u4e0a\u7684\u6811\u8393\u6d3e\uff08\u7cfb\u7edf\u7248\u672c\uff1aNovember 2017\uff09\u5df2\u7ecf\u5185\u7f6e Node.js 4.x \u7248\u672c\u3002\u4e3a\u4e86\u4fdd\u6301\u7cfb\u7edf\u5e72\u51c0\u6574\u6d01\uff0c\u4e0d\u60f3\u4f7f\u7528\u6e90\u7801\u7f16\u8bd1\u6765\u66f4\u65b0\uff0c\u672c\u6587\u5c06\u8bb2\u89e3\u5982\u4f55\u64cd\u4f5c\u3002\n 0x00 \u5378\u8f7d \u5378\u8f7d\u539f\u6709 node.js \u4ee5\u53ca npm\u3002\nsudo apt-get remove nodejs npm sudo apt autoremove 0x01 \u5b89\u88c5 \u5b89\u88c5\u524d\uff0c\u6211\u4eec\u9700\u8981\u66f4\u65b0 apt \u6e90\u4e3a\u5305\u542b\u6307\u5b9a node.","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0 - \u4f7f\u7528 apt-get \u5347\u7ea7\u5185\u7f6e Node.js"},{"content":" \u524d\u51e0\u5929\u59b9\u5b50\u9001\u4e86\u4e2a\u751f\u65e5\u793c\u7269\u2014\u2014\u6811\u8393\u6d3e\uff0c\u60f3\u5230\u516c\u53f8\u95e8\u7981\u8fd8\u662f\u6307\u7eb9\u89e3\u9501\uff0c\u968f\u5373\u8bf4\u5e72\u5c31\u5e72\uff0c\u5f00\u59cb\u6298\u817e\u4e2a\u4eba\u8138\u95e8\u7981\u987a\u4fbf\u5165\u95e8\u5427\u3002\n 0x00 \u601d\u8def \u6700\u5f00\u59cb\u6211\u7684\u60f3\u6cd5\u662f\u7531\u6811\u8393\u6d3e\u72ec\u7acb\u5b8c\u6210\u6444\u50cf\u5934\u56fe\u50cf\u6355\u6349\u3001\u4eba\u8138\u68c0\u6d4b\u3001\u6bd4\u5bf9\uff1b\u8f6c\u5ff5\u4e00\u60f3\uff0c\u540e\u671f\u8fd9\u73a9\u610f\u53ef\u4ee5\u8fce\u5408\u516c\u53f8\u9879\u76ee\uff0c\u653e\u5230\u653f\u4f01\u4e13\u7f51\u5185\u90e8\u8fd0\u4f5c\uff0c\u8fd8\u662f C\uff0fS \u6bd4\u8f83\u5408\u9002\uff08\u66f4\u65b0\u65b9\u4fbf\u3001\u7edf\u4e00\u7ba1\u7406\u3001Client \u7aef\u5e73\u53f0\u65e0\u9650\u5236\uff09\uff1b\u540e\u6765\u53d7\u5230\u516c\u53f8\u53e6\u4e00\u4e2a\u5c0f\u4f19\u4f34\u7684\u542f\u53d1\uff0c\u65e2\u7136\u91c7\u7528 C\uff0fS \u67b6\u6784\uff0c\u90a3\u670d\u52a1\u5668\u7aef\u80af\u5b9a\u662f x64 \u7684 CPU\uff0c\u53ef\u4ee5\u8c03\u7528\u8679\u8f6f\u4eba\u8138 SDK\uff0c\u907f\u514d\u4f7f\u7528\u5f00\u6e90\u7b97\u6cd5\u5934\u75bc\u4f18\u5316\u95ee\u9898\uff0c\u6240\u4ee5\u6700\u7ec8\u7684\u7ed3\u6784\u57fa\u672c\u662f\u8fd9\u6837\u7684\uff1a\n\uff08\u51d1\u5408\u770b\u5427\u2026\u2026\u6bd5\u7adf\u662f\u81ea\u5df1\u6574\u7406\u601d\u8def\u7684\u65f6\u5019\u968f\u624b\u753b\u7684\uff09\n0x01 \u51c6\u5907 \u786c\u4ef6  \u6811\u8393\u6d3e 3B \u7f57\u6280 C170 \u6444\u50cf\u5934\uff08\u8857\u8fb9\u7535\u8111\u5e97\u4e70\u7684\uff09 Linux \u670d\u52a1\u5668\u4e00\u53f0\uff08with x64 CPU\uff09  \u8f6f\u4ef6  C Node.js \u8679\u8f6f SDK  0x02 \u6298\u817e \u6811\u8393\u6d3e: \u5b89\u88c5\u7cfb\u7edf  \u64cd\u4f5c\u7cfb\u7edf\u5927\u5168 \u5728 macOS \u4e0a\u5199\u5165\u7cfb\u7edf\u955c\u50cf \u8fde\u63a5 WiFi - \u65b9\u6cd5 1 \u8fde\u63a5 WiFi - \u65b9\u6cd5 2 \u8fde\u63a5 WiFi - \u65b9\u6cd5 3 \u5b89\u5168\u5173\u673a\u91cd\u542f\u547d\u4ee4 VNC \u53ef\u89c6\u5316\u8fdc\u7a0b  \u6811\u8393\u6d3e: USB \u6444\u50cf\u5934\u652f\u6301\u5217\u8868  USB Webcams  \u6811\u8393\u6d3e: \u8fde\u63a5\u6444\u50cf\u5934  fswebcam \u7f57\u6280 C170 \u62a5\u9519\u95ee\u9898(\u4e0d\u652f\u6301 RGB \u901a\u9053,\u5fc5\u987b\u4f7f\u7528-p YUYV) mplayer  \u6811\u8393\u6d3e: Node.js \u8fde\u63a5\u6444\u50cf\u5934  web \u8c03\u8bd5\u6811\u8393\u6d3e\u6444\u50cf\u5934 \u6811\u8393\u6d3e&#43;\u6444\u50cf\u5934: Node.js \u6253\u9020 1D\/2D \u6761\u7801\u626b\u63cf\u4eea node-v4l2camera jpeg-js jsmpeg  \u670d\u52a1\u5668(C): \u7f16\u8bd1\u8679\u8f6f SDK \u4f8b\u7a0b  error: \u2018nullptr\u2019 was not declared in this scope cannot open shared object file: No such file or directory   \u6ca1\u9519, \u73a9 C++ \u6700\u96be\u7684, \u5c31\u662f\u7f16\u8bd1&hellip; 2333\n \u670d\u52a1\u5668(C): \u5c01\u88c5\u5e76\u7f16\u8bd1\u52a8\u6001\u94fe\u63a5\u5e93  C \u7f16\u8bd1: \u52a8\u6001\u8fde\u63a5\u5e93 (.so \u6587\u4ef6) GCC \u7f16\u8bd1\u52a8\u6001\u94fe\u63a5\u5e93 .so \u52a8\u6001\u5e93 makefile \u7684\u5d4c\u5957\u8c03\u7528 Linux \u4e0b so \u5bfc\u51fa\u6307\u5b9a\u51fd\u6570  \u670d\u52a1\u5668(Node): \u8c03\u7528\u52a8\u6001\u94fe\u63a5\u5e93  node-ffi  \u670d\u52a1\u5668(Bash): \u56fe\u7247\u8f6c YUV \u901a\u9053\u539f\u59cb\u6570\u636e  ffmpeg jpeg \u8f6c yuv422p(420p)  \u670d\u52a1\u5668(Node): \u5b9e\u73b0\u4eba\u8138 HTTP API  Node.js \u8fdc\u7a0b\u8c03\u8bd5 node.js \u5982\u4f55\u5b8c\u7f8e\u7684\u4ece\u547d\u4ee4\u884c\u63a5\u6536\u53c2\u6570\u6240\u4f20\u9012\u8fdb\u6765\u7684\u503c Nodejs \u8fdb\u9636\uff1a\u57fa\u4e8e express&#43;multer \u7684\u6587\u4ef6\u4e0a\u4f20 nodejs \u4e2d\u7684\u4e2d\u95f4\u4ef6&amp;ndash;Multer  \u6811\u8393\u6d3e: \u8c03\u7528\u4eba\u8138 API  Request - Simplified HTTP client  \u5176\u5b83  OpenCV and Pi Camera Board \u6811\u8393\u6d3e\u4eba\u8138\u8bc6\u522b\u95e8\u7981\u7cfb\u7edf\u4ee3\u7801\u4ee5\u53ca\u4ee3\u7801\u5206\u6790\u2014\u2014opencv \u62cd\u7167\u8c03\u7528 FACE&#43;&#43;\u5904\u7406 \u3010Raspberry Pi 3 \u8bd5\u7528\u4f53\u9a8c\u3011&#43;Opencv&#43;python \u7684\u4eba\u8138\u8bc6\u522b \u4f7f\u7528\u6811\u8393\u6d3e\u8fdb\u884c\u7b80\u6613\u4eba\u8138\u8bc6\u522b \u6811\u8393\u6d3e\u4e00\u952e\u90e8\u7f72\u7cfb\u5217\u4e4b\u4e8c\uff1aopenface \u4eba\u8138\u8bc6\u522b\u7a0b\u5e8f  0x03 \u6210\u679c \u5b9e\u65f6\u5237\u65b0:\n \u5355\u7ebf\u7a0b\u57fa\u672c\u4e0a\u6bcf\u79d2 2-3 \u5e27, \u56e0\u4e3a\u8bc6\u522b\u5728\u670d\u52a1\u5668, \u6240\u4ee5\u51e0\u4e4e\u4e0d\u5b58\u5728\u6027\u80fd\u95ee\u9898, \u53ea\u8981\u5e26\u5bbd\u591f, \u6709\u591a\u5c11 frames \u5c31\u80fd\u8bc6\u522b\u591a\u5c11.\n \u5168\u5bb6\u798f:\n \u539f\u8c05\u6211\u4e0d\u662f\u4e2a\u4e13\u4e1a\u786c\u4ef6\u5de5\u7a0b\u5e08, \u53ea\u4f1a\u7b80\u6d01\u7684\u8fde\u7ebf\u98ce\u683c, lol.\n 0x04 \u540e\u8bb0 \u6ca1\u6709\u540e\u8bb0, \u795d\u81ea\u5df1\u751f\u65e5\u5feb\u4e50\u7684\u540c\u65f6, \u4e5f\u5e0c\u671b 2018 \u5927\u5409\u5927\u5229, \u59b9\u5b50\u5230\u624b (\u6b63\u7ecf\u8138).\n","permalink":"https:\/\/wi1dcard.dev\/posts\/raspberry-pi-face-recognition\/","summary":"\u524d\u51e0\u5929\u59b9\u5b50\u9001\u4e86\u4e2a\u751f\u65e5\u793c\u7269\u2014\u2014\u6811\u8393\u6d3e\uff0c\u60f3\u5230\u516c\u53f8\u95e8\u7981\u8fd8\u662f\u6307\u7eb9\u89e3\u9501\uff0c\u968f\u5373\u8bf4\u5e72\u5c31\u5e72\uff0c\u5f00\u59cb\u6298\u817e\u4e2a\u4eba\u8138\u95e8\u7981\u987a\u4fbf\u5165\u95e8\u5427\u3002\n 0x00 \u601d\u8def \u6700\u5f00\u59cb\u6211\u7684\u60f3\u6cd5\u662f\u7531\u6811\u8393\u6d3e\u72ec\u7acb\u5b8c\u6210\u6444\u50cf\u5934\u56fe\u50cf\u6355\u6349\u3001\u4eba\u8138\u68c0\u6d4b\u3001\u6bd4\u5bf9\uff1b\u8f6c\u5ff5\u4e00\u60f3\uff0c\u540e\u671f\u8fd9\u73a9\u610f\u53ef\u4ee5\u8fce\u5408\u516c\u53f8\u9879\u76ee\uff0c\u653e\u5230\u653f\u4f01\u4e13\u7f51\u5185\u90e8\u8fd0\u4f5c\uff0c\u8fd8\u662f C\uff0fS \u6bd4\u8f83\u5408\u9002\uff08\u66f4\u65b0\u65b9\u4fbf\u3001\u7edf\u4e00\u7ba1\u7406\u3001Client \u7aef\u5e73\u53f0\u65e0\u9650\u5236\uff09\uff1b\u540e\u6765\u53d7\u5230\u516c\u53f8\u53e6\u4e00\u4e2a\u5c0f\u4f19\u4f34\u7684\u542f\u53d1\uff0c\u65e2\u7136\u91c7\u7528 C\uff0fS \u67b6\u6784\uff0c\u90a3\u670d\u52a1\u5668\u7aef\u80af\u5b9a\u662f x64 \u7684 CPU\uff0c\u53ef\u4ee5\u8c03\u7528\u8679\u8f6f\u4eba\u8138 SDK\uff0c\u907f\u514d\u4f7f\u7528\u5f00\u6e90\u7b97\u6cd5\u5934\u75bc\u4f18\u5316\u95ee\u9898\uff0c\u6240\u4ee5\u6700\u7ec8\u7684\u7ed3\u6784\u57fa\u672c\u662f\u8fd9\u6837\u7684\uff1a\n\uff08\u51d1\u5408\u770b\u5427\u2026\u2026\u6bd5\u7adf\u662f\u81ea\u5df1\u6574\u7406\u601d\u8def\u7684\u65f6\u5019\u968f\u624b\u753b\u7684\uff09\n0x01 \u51c6\u5907 \u786c\u4ef6  \u6811\u8393\u6d3e 3B \u7f57\u6280 C170 \u6444\u50cf\u5934\uff08\u8857\u8fb9\u7535\u8111\u5e97\u4e70\u7684\uff09 Linux \u670d\u52a1\u5668\u4e00\u53f0\uff08with x64 CPU\uff09  \u8f6f\u4ef6  C Node.","title":"\u6811\u8393\u6d3e\u6298\u817e\u968f\u624b\u8bb0 - \u4eba\u8138\u95e8\u7981"},{"content":"\u5728\u524d\u7aef\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u5e38\u89c1\u8def\u5f84\uff0c\u5728\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u540c\u7ad9\u70b9\u5f3a\u70c8\u5efa\u8bae\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\uff0c\u8fd9\u91cc\u7b80\u5355\u603b\u7ed3\u4e00\u4e0b\u76f8\u5bf9\u8def\u5f84\u7684\u5199\u6cd5\u3002\n  .\/***\uff0c\u300c.\u300d\u7528\u6765\u8868\u793a\u5f53\u524d\u76ee\u5f55\uff0c\u6b64\u5199\u6cd5\u7528\u4e8e\u5f15\u7528\u548c\u672c\u9875\u9762\u76f8\u540c\u76ee\u5f55\u4e0b\u7684\u5176\u4ed6\u6587\u4ef6\u3002\n  ..\/***\uff0c\u300c..\u300d\u7528\u6765\u8868\u793a\u4e0a\u7ea7\u76ee\u5f55\uff0c\u5373\u7236\u76ee\u5f55\u3002\u4ee5\u6b64\u7c7b\u63a8\uff0c\u53ef\u4ee5\u4f7f\u7528..\/..\/\u6765\u8868\u793a\u4e0a\u7ea7\u76ee\u5f55\u7684\u4e0a\u7ea7\u76ee\u5f55\u3002\n  \/****\uff0c\u300c\/\u300d\u8868\u793a\u540c\u7ad9\u70b9\u8ddf\u76ee\u5f55\u3002\u65e0\u8bba\u672c\u9875\u9762\u76ee\u5f55\u662f\u5728\u54ea\uff0c\u6b64\u5199\u6cd5\u90fd\u80fd\u5f15\u7528\u5230\u6839\u76ee\u5f55\uff0c\u5e38\u89c1\u7528\u6cd5\u4f8b\u5982 favicon\u3002\n  \/\/****\uff0c\u300c\/\/\u300d\u8868\u793a\u76f8\u540c\u534f\u8bae\u3002\u6b64\u5199\u6cd5\u4e0e\u7edd\u5bf9\u8def\u5f84\u7684\u533a\u522b\u5c31\u5728\u4e8e\u4e0d\u6307\u5b9a\u534f\u8bae\uff0c\u5177\u4f53\u534f\u8bae\u5c06\u8ddf\u968f\u5f53\u524d\u9875\u9762\uff0c\u5e38\u89c1\u7528\u6cd5\u4f8b\u5982\u5168\u7ad9 HTTPS\u3002\n  \u6709\u8fc7 Linux \u529f\u5e95\u7684\u540c\u5b66\u5e94\u8be5\u4f1a\u53d1\u73b0\uff0c\u5982\u4e0a\u7684\u8def\u5f84\u5199\u6cd5\u90fd\u662f\u6807\u51c6\u7684 URI\uff0cLinux \u7684\u6587\u4ef6\u8def\u5f84\u4e5f\u540c\u6837\u9075\u5faa\u4e86 URI \u7684\u6807\u51c6\u3002\u5177\u4f53\u4f8b\u5b50\u5728\u8fd9\u91cc\u4e0d\u518d\u8be6\u53d9\uff0c\u968f\u4fbf\u5f00\u4e2a\u767e\u5ea6\u3001\u6dd8\u5b9d\u7684\u9875\u9762\u4e00\u6293\u4e00\u5927\u628a\uff0c\u81ea\u5df1\u5b9e\u8df5\u4e00\u4e0b\u4e5f\u662f\u4e0d\u9519\u7684\u5b66\u4e60\u65b9\u5f0f\u3002\n\u6269\u5c55\uff1a\n\u76f8\u5bf9\u8def\u5f84 Or \u7edd\u5bf9\u8def\u5f84&amp;ndash;\u524d\u7aef\u4f18\u5316(\u4e00)\nUniform Resource Identifier - Wikipedia\n","permalink":"https:\/\/wi1dcard.dev\/posts\/html-relative-uri\/","summary":"\u5728\u524d\u7aef\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u5e38\u89c1\u8def\u5f84\uff0c\u5728\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u540c\u7ad9\u70b9\u5f3a\u70c8\u5efa\u8bae\u4f7f\u7528\u76f8\u5bf9\u8def\u5f84\uff0c\u8fd9\u91cc\u7b80\u5355\u603b\u7ed3\u4e00\u4e0b\u76f8\u5bf9\u8def\u5f84\u7684\u5199\u6cd5\u3002\n  .\/***\uff0c\u300c.\u300d\u7528\u6765\u8868\u793a\u5f53\u524d\u76ee\u5f55\uff0c\u6b64\u5199\u6cd5\u7528\u4e8e\u5f15\u7528\u548c\u672c\u9875\u9762\u76f8\u540c\u76ee\u5f55\u4e0b\u7684\u5176\u4ed6\u6587\u4ef6\u3002\n  ..\/***\uff0c\u300c..\u300d\u7528\u6765\u8868\u793a\u4e0a\u7ea7\u76ee\u5f55\uff0c\u5373\u7236\u76ee\u5f55\u3002\u4ee5\u6b64\u7c7b\u63a8\uff0c\u53ef\u4ee5\u4f7f\u7528..\/..\/\u6765\u8868\u793a\u4e0a\u7ea7\u76ee\u5f55\u7684\u4e0a\u7ea7\u76ee\u5f55\u3002\n  \/****\uff0c\u300c\/\u300d\u8868\u793a\u540c\u7ad9\u70b9\u8ddf\u76ee\u5f55\u3002\u65e0\u8bba\u672c\u9875\u9762\u76ee\u5f55\u662f\u5728\u54ea\uff0c\u6b64\u5199\u6cd5\u90fd\u80fd\u5f15\u7528\u5230\u6839\u76ee\u5f55\uff0c\u5e38\u89c1\u7528\u6cd5\u4f8b\u5982 favicon\u3002\n  \/\/****\uff0c\u300c\/\/\u300d\u8868\u793a\u76f8\u540c\u534f\u8bae\u3002\u6b64\u5199\u6cd5\u4e0e\u7edd\u5bf9\u8def\u5f84\u7684\u533a\u522b\u5c31\u5728\u4e8e\u4e0d\u6307\u5b9a\u534f\u8bae\uff0c\u5177\u4f53\u534f\u8bae\u5c06\u8ddf\u968f\u5f53\u524d\u9875\u9762\uff0c\u5e38\u89c1\u7528\u6cd5\u4f8b\u5982\u5168\u7ad9 HTTPS\u3002\n  \u6709\u8fc7 Linux \u529f\u5e95\u7684\u540c\u5b66\u5e94\u8be5\u4f1a\u53d1\u73b0\uff0c\u5982\u4e0a\u7684\u8def\u5f84\u5199\u6cd5\u90fd\u662f\u6807\u51c6\u7684 URI\uff0cLinux \u7684\u6587\u4ef6\u8def\u5f84\u4e5f\u540c\u6837\u9075\u5faa\u4e86 URI \u7684\u6807\u51c6\u3002\u5177\u4f53\u4f8b\u5b50\u5728\u8fd9\u91cc\u4e0d\u518d\u8be6\u53d9\uff0c\u968f\u4fbf\u5f00\u4e2a\u767e\u5ea6\u3001\u6dd8\u5b9d\u7684\u9875\u9762\u4e00\u6293\u4e00\u5927\u628a\uff0c\u81ea\u5df1\u5b9e\u8df5\u4e00\u4e0b\u4e5f\u662f\u4e0d\u9519\u7684\u5b66\u4e60\u65b9\u5f0f\u3002","title":"URI \u76f8\u5bf9\u8def\u5f84\u5199\u6cd5"},{"content":"\u524d\u6bb5\u65f6\u95f4\u8c37\u6b4c\u628a .dev \u4e70\u4e86\uff0c\u6211\u6709\u6240\u8033\u95fb\uff0c\u4f46\u8fd9\u6bb5\u65f6\u95f4\u4e00\u76f4\u6ca1\u6709\u505a Web \u5f00\u53d1\uff0c\u4eca\u5929\u5ffd\u7136\u53d1\u73b0 ***.dev \u6253\u4e0d\u5f00\u4e86\uff0c\u6545\u6392\u67e5\u539f\u56e0\u3002\n0x01 \u6700\u5f00\u59cb\u4ee5\u4e3a\u662f dnsmasq \u6302\u4e86\uff0c\u7ecf\u8fc7\u4e00\u756a\u8c37\u6b4c\u548c ping \u68c0\u67e5\uff0c\u53d1\u73b0\u80fd\u591f\u6b63\u5e38\u89e3\u6790\u5230 127.0.0.1\u3002\nValet (Laravel): DNS address can not be found\n0x02 \u641e\u5230\u8fd9\u7a81\u7136\u60f3\u8d77\u6765\u524d\u4e9b\u65e5\u5b50\u7684\u4e8b\u60c5\uff0c\u539f\u6765\u662f\u8c37\u6b4c\u201c\u60f9\u7684\u7978\u201d\u3002\u968f\u5373\u7ee7\u7eed\u201c\u8c37\u6b4c\u201d\u4e00\u756a\u6765\u89e3\u51b3\u5b83\u81ea\u5df1\u60f9\u7684\u7978\u3002\nChrome to force https on .dev\n\u627e\u5230\u5b98\u65b9\u89e3\u51b3\u65b9\u6848\uff0c\u4f7f\u7528\u547d\u4ee4\uff1avalet domain ***\uff0c\u5373\u53ef\u66ff\u6362\u539f\u6709\u57df\u540d\u540e\u7f00\u3002\n\u5982\u56fe\uff0c\u6211\u5c06\u57df\u540d\u540e\u7f00\u4fee\u6539\u4e3a.localhost\uff0c\u968f\u5373 valet \u81ea\u52a8\u91cd\u542f\uff0c\u95ee\u9898\u89e3\u51b3\u3002\n\u540e\u8bb0\uff1a\u8f93\u9519\u4e24\u6b21\u5bc6\u7801\u6709\u70b9\u5c2c\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/chrome-to-force-https-valet-domain\/","summary":"\u524d\u6bb5\u65f6\u95f4\u8c37\u6b4c\u628a .dev \u4e70\u4e86\uff0c\u6211\u6709\u6240\u8033\u95fb\uff0c\u4f46\u8fd9\u6bb5\u65f6\u95f4\u4e00\u76f4\u6ca1\u6709\u505a Web \u5f00\u53d1\uff0c\u4eca\u5929\u5ffd\u7136\u53d1\u73b0 ***.dev \u6253\u4e0d\u5f00\u4e86\uff0c\u6545\u6392\u67e5\u539f\u56e0\u3002\n0x01 \u6700\u5f00\u59cb\u4ee5\u4e3a\u662f dnsmasq \u6302\u4e86\uff0c\u7ecf\u8fc7\u4e00\u756a\u8c37\u6b4c\u548c ping \u68c0\u67e5\uff0c\u53d1\u73b0\u80fd\u591f\u6b63\u5e38\u89e3\u6790\u5230 127.0.0.1\u3002\nValet (Laravel): DNS address can not be found","title":"Chrome \u5360\u7528 *.dev \u5bfc\u81f4 Valet \u5931\u6548\u7684\u89e3\u51b3\u65b9\u6848"},{"content":"\u524d\u8a00 \u67d0\u516c\u5b89\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u5728\u5185\u7f51\u670d\u52a1\u5668\u90e8\u7f72 WNMP \u73af\u5883\uff0c\u8fd0\u884c Laravel \u6846\u67b6\u4ee3\u7801\uff0c\u540e\u67e5\u770b\u65e5\u5fd7\u53d1\u73b0\u67d0\u4e00\u65f6\u523b\u7a81\u7136\u6240\u6709\u8bf7\u6c42 499\uff0c\u5e76\u6301\u7eed\u4e00\u6bb5\u65f6\u95f4\uff0c\u9042\u6392\u67e5\u539f\u56e0\u3002\n\u8fc7\u7a0b 0x01 \u7ecf\u641c\u7d22\u5f97\u77e5\uff1a \u54ea\u4e9b\u60c5\u51b5\u4e0b\u4f1a\u4f7f Nginx \u8fd4\u56de HTTP CODE 499\uff1f\n \u5373\uff1a\u300c\u5ba2\u6237\u7aef\u4e3b\u52a8\u5173\u95ed\u8fde\u63a5\u300d\n \u4f46\u67d0\u4e00\u65f6\u95f4\u6bb5\u5185\u5168\u90e8\u8bf7\u6c42\u5747\u4e3a\u8fd4\u56de 499\uff0c\u8fd9\u663e\u7136\u4e0d\u662f\u6240\u6709\u5ba2\u6237\u7aef\u4e3b\u52a8\u610f\u8bc6\u4e0a\u7684\u300c\u5173\u95ed\u300d\uff0c\u53ef\u80fd\u662f\u56e0\u4e3a\u5ba2\u6237\u7aef\u7b49\u5f85\u8d85\u65f6\uff0c\u81ea\u52a8\u5173\u95ed\u8fde\u63a5\uff1b\u52a0\u4e0a 499 \u7684\u65f6\u95f4\u6bb5\u5185\u5305\u542b\u90e8\u5206 502\uff0c\u8ba9\u6211\u4e0d\u5f97\u4e0d\u6000\u7591\uff1a\n PHP \u8fdb\u7a0b\u300c\u6b7b\u300d\u4e86\u3002\n 0x02 \u8fd9\u91cc\u7684\u6b7b\uff0c\u4e0d\u4e00\u5b9a\u662f\u8fdb\u7a0b\u7ed3\u675f\uff0c\u4e5f\u6709\u53ef\u80fd\u662f\u50f5\u5c38\uff0c\u6216\u662f\u9677\u5165\u6b7b\u5faa\u73af\uff0c\u4e00\u76f4\u5728\u6267\u884c\u67d0\u4e2a\u811a\u672c\u2026\u2026\n\u82e5\u662f\u9010\u4e2a\u68c0\u67e5\u4ee3\u7801\u65f6\u95f4\u6765\u4e0d\u53ca\uff08\u4ee5\u5148\u89e3\u51b3\u95ee\u9898\u4e3a\u91cd\uff09\uff0c\u9042\u6392\u67e5\uff1a Nginx&#43;FastCGI \u5230\u5e95\u662f\u8c01\u5f71\u54cd\u8d85\u65f6\u65f6\u95f4\n\u4ee5\u53ca\uff1a PHP-max_execution_time \u4e0e fpm.request_terminate_timeout \u4ecb\u7ecd\n0x03 \u7ecf\u8fc7\u4e0a\u9762\u7684\u8c03\u6574\uff0c\u5927\u7ea6\u4e00\u5468\u540e\u518d\u6b21\u7ef4\u62a4\u670d\u52a1\u5668\u3002\u53d1\u73b0\u60c5\u51b5\u6709\u6240\u6539\u5584\u2014\u2014 499 \u9519\u8bef\u5df2\u7ecf\u7531\u67d0\u4e00\u65f6\u6bb5\u5927\u91cf\u3001\u96c6\u4e2d\u51fa\u73b0\u53d8\u4e3a\u5076\u5c14\u53d1\u751f\uff0c\u4e14\u53ea\u51fa\u73b0\u5728\u67d0\u51e0\u4e2a\u7279\u5b9a URI \u8bf7\u6c42\u4e0a\u3002\n\u6211\u51b3\u5b9a\u5bf9\u8fd9\u51e0\u4e2a URI \u5bf9\u5e94\u7684\u63a5\u53e3\u63a7\u5236\u5668\u4ee3\u7801\u8fdb\u884c\u68c0\u67e5\u3002\u7531\u4e8e\u7cfb\u7edf\u5f00\u53d1\u65f6\u95f4\u7d27\u5f20\uff0c\u4ee3\u7801\u8d28\u91cf\u5e76\u4e0d\u9ad8\uff0c\u6000\u7591\u662f\u5426\u662f\u7a0b\u5e8f\u5185\u6709 BUG\u3002\n\u9996\u5148\u67e5\u770b\u4ee3\u7801\u6267\u884c\u65f6\u95f4\uff0c\u7ea6\u4e3a 1900 ms \u5de6\u53f3\uff0c\u7b80\u76f4\u592a\u6162\uff01\u7ecf\u8fc7\u4ed4\u7ec6\u68c0\u67e5\uff0c\u53d1\u73b0\u51e0\u4e2a\u4e25\u91cd\u95ee\u9898\uff1a\n \u67e5\u51fa\u67d0\u8868\u300c\u5168\u90e8\u7ed3\u679c\u300d\uff0c\u518d\u300c\u904d\u5386\u300d\u7ed3\u679c\u96c6\uff0c\u67e5\u8be2\u6bcf\u6761\u8bb0\u5f55\u300c\u591a\u4e2a\u5b57\u6bb5\u300d\u7684\u5173\u8054\u6a21\u578b \u672a\u6267\u884c php artisan optimize \u672a\u5173\u95ed debug \u6a21\u5f0f \u672a\u8c03\u6574 log_level  \u5176\u4e2d\uff0c\u540e\u51e0\u6761\u6216\u8bb8\u65e0\u5173\u7d27\u8981\uff0c\u4f46\u7b2c\u4e00\u6761\u7edd\u5bf9\u662f\u81f4\u547d\u7684\u3002\n\u5047\u8bbe\u4e00\u79cd\u5e38\u89c1\u7684\u6a21\u578b\u5173\u8054\u573a\u666f\uff1a\n\u67d0\u4f5c\u8005\u6709\u591a\u7bc7\u6587\u7ae0\uff0c\u6bcf\u7bc7\u6587\u7ae0\u53c8\u6709\u591a\u6761\u8bc4\u8bba\u3001\u8d5e\u3002\n\u7531\u6b64\uff0c\u82e5\u662f\u91c7\u7528\u7c7b\u4f3c\uff1a\nposts = posts::where('user_id', 1); foreach(posts as post){ likes = post-&gt;likes; comments = post-&gt;comments; } \u5728 Laravel \u6846\u67b6\u5185\u4f7f\u7528\u7c7b\u4f3c\u5982\u4e0a\u7684\u65b9\u5f0f\u67e5\u8be2\uff0c\u5047\u8bbe\u4f5c\u8005\u7684\u6587\u7ae0\u6570\u4e3a n\uff0c\u6bcf\u7bc7\u6587\u7ae0\u5173\u8054\u7684\u6a21\u578b\u6709 2 \u4e2a\uff08likes &amp; comments\uff09\uff0c\u5219\u6267\u884c\u6b64\u63a7\u5236\u5668\uff0c\u5bf9\u4e8e\u6570\u636e\u5e93\u7684\u65f6\u95f4\u590d\u6742\u5ea6\u4e3a\uff1aO(n*2+1)\uff0c\u9700\u8981\u6267\u884c\u5982\u6b64\u5927\u91cf\u7684 SQL \u8bed\u53e5\uff01\u8fd9\u5728\u540e\u7aef\u8bbe\u8ba1\u4e2d\u5e94\u8be5\u662f\u9700\u8981\u5b8c\u5168\u907f\u514d\u7684\uff0c\u7406\u60f3\u60c5\u51b5\u7684\u65f6\u95f4\u590d\u6742\u5ea6\u5e94\u8be5\u662f O(n)\uff0cn \u4e3a\u5e38\u91cf\uff0c\u4e0d\u53d7\u6570\u636e\u89c4\u6a21\u7684\u5f71\u54cd\u3002\n\u4e8e\u662f\u4fee\u6539\u4ee3\u7801\uff0c\u8fc7\u7a0b\u4e0d\u518d\u8be6\u53d9\uff0c\u53c2\u89c1 Laravel \u5b98\u65b9\u6587\u6863\uff0c\u6216\uff1a Laravel \u5b66\u4e60\u7b14\u8bb0\u4e4b\u6a21\u578b\u5173\u8054\u9884\u52a0\u8f7d\n\u7ecf\u8fc7\u4fee\u6539\uff0c\u5728 Chrome \u5f00\u53d1\u8005\u5de5\u5177\u5185\u67e5\u770b\u8bf7\u6c42 Timing\uff0c\u7f29\u77ed\u4e3a\u539f\u6765\u65f6\u95f4\u7684\u4e00\u534a\uff0c800ms \u5de6\u53f3\u3002\n\uff08\u4f46\u6b64\u503c\u4ecd\u7136\u4e0d\u591f\u7406\u60f3\uff0c\u53d7\u5230\u89c6\u56fe\u6e32\u67d3\u3001\u64cd\u4f5c\u7cfb\u7edf\u7b49\u539f\u56e0\u7684\u5f71\u54cd\uff0c\u540e\u671f\u7ee7\u7eed\u4f18\u5316\uff0c\u4e0d\u5c5e\u4e8e\u672c\u6587\u8ba8\u8bba\u8303\u56f4\u3002\uff09\n\u540e\u8bb0 \u5bf9\u4e8e\u90e8\u5206\u63a5\u53e3\uff0c\u8bf7\u6c42\u4e00\u6b21\u9700\u8981\u6267\u884c\u51e0\u767e\u6761 SQL\uff1b\u90a3\u4e48\uff0c\u56de\u5230\u6700\u5f00\u59cb\u7684\u95ee\u9898\uff1a\n\u67d0\u6b21\u8bf7\u6c42\u540e\uff0c\u7a81\u7136\u5f15\u53d1\u5927\u91cf 499\u3002\u7a76\u5176\u6839\u672c\u539f\u56e0\uff0c\u662f\u5426\u5728\u4e8e\u56e0\u4ee3\u7801\u7684\u4e0d\u4e25\u8c28\uff0c\u5f15\u8d77\u7684 MySQL \u6b7b\u9501\u5462\uff1f\n\u503c\u5f97\u7814\u8ba8\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/nginx-php-http-status-499\/","summary":"\u524d\u8a00 \u67d0\u516c\u5b89\u9879\u76ee\u8fc7\u7a0b\u4e2d\uff0c\u5728\u5185\u7f51\u670d\u52a1\u5668\u90e8\u7f72 WNMP \u73af\u5883\uff0c\u8fd0\u884c Laravel \u6846\u67b6\u4ee3\u7801\uff0c\u540e\u67e5\u770b\u65e5\u5fd7\u53d1\u73b0\u67d0\u4e00\u65f6\u523b\u7a81\u7136\u6240\u6709\u8bf7\u6c42 499\uff0c\u5e76\u6301\u7eed\u4e00\u6bb5\u65f6\u95f4\uff0c\u9042\u6392\u67e5\u539f\u56e0\u3002\n\u8fc7\u7a0b 0x01 \u7ecf\u641c\u7d22\u5f97\u77e5\uff1a \u54ea\u4e9b\u60c5\u51b5\u4e0b\u4f1a\u4f7f Nginx \u8fd4\u56de HTTP CODE 499\uff1f\n \u5373\uff1a\u300c\u5ba2\u6237\u7aef\u4e3b\u52a8\u5173\u95ed\u8fde\u63a5\u300d\n \u4f46\u67d0\u4e00\u65f6\u95f4\u6bb5\u5185\u5168\u90e8\u8bf7\u6c42\u5747\u4e3a\u8fd4\u56de 499\uff0c\u8fd9\u663e\u7136\u4e0d\u662f\u6240\u6709\u5ba2\u6237\u7aef\u4e3b\u52a8\u610f\u8bc6\u4e0a\u7684\u300c\u5173\u95ed\u300d\uff0c\u53ef\u80fd\u662f\u56e0\u4e3a\u5ba2\u6237\u7aef\u7b49\u5f85\u8d85\u65f6\uff0c\u81ea\u52a8\u5173\u95ed\u8fde\u63a5\uff1b\u52a0\u4e0a 499 \u7684\u65f6\u95f4\u6bb5\u5185\u5305\u542b\u90e8\u5206 502\uff0c\u8ba9\u6211\u4e0d\u5f97\u4e0d\u6000\u7591\uff1a","title":"Nginx+PHP \u73af\u5883 499 \u9519\u8bef\u7801\u6392\u67e5\u8fc7\u7a0b\u5c0f\u8bb0"},{"content":" \u5728\u5404\u7c7b\u4ea4\u6d41\u7fa4\uff0c\u751a\u81f3\u591a\u6570\u8001\u4e00\u8f88\u7a0b\u5e8f\u5458\u7684\u773c\u91cc\uff0c\u8ba4\u4e3a PHP \u662f\u300c\u8f7b\u91cf\u7684\u300d\u3001\u300c\u4e0d\u5b8c\u5584\u7684\u300d\u3001\u300c\u6027\u80fd\u96be\u4ee5\u4f18\u5316\u300d\u7684\uff0c\u800c\u8fd9\u4e48\u591a\u5e74\u6765\u4e00\u76f4\u575a\u633a\u7684 Java \u5374\u6210\u4e86\u5f00\u53d1\u300cXX \u7cfb\u7edf\u300d\u7684\u540e\u7aef\u9996\u9009\u8bed\u8a00\u3002\u4e3a\u6b64\uff0c\u672c\u7bc7\u6587\u7ae0\u5c06\u5c3d\u91cf\u4ece\u975e\u6280\u672f\u89d2\u5ea6\u544a\u8bc9\u5927\u5bb6\uff1aWhy PHP\uff1f\n \u73b0\u72b6 \u5176\u5b9e\uff0c\u4ece Java \u548c PHP \u7684\u5386\u53f2\u4e0d\u96be\u770b\u51fa\u3002\u5728 Java \u5f00\u59cb\u76db\u884c\u7684\u5e74\u4ee3\uff0cPHP \u8fd8\u662f\u4e2a\u201c\u6bdb\u5934\u5c0f\u5b50\u201d\uff0c\u53ea\u662f\u4e2a\u666e\u666e\u901a\u901a\u7684\u811a\u672c\u8bed\u8a00\u7f62\u4e86\uff0c\u751a\u81f3\u8fde\u9762\u5411\u5bf9\u8c61\u7684\u57fa\u672c\u6982\u5ff5\u2014\u2014\u7c7b\uff0c\u90fd\u6ca1\u6709\u652f\u6301\u3002\n \u9274\u4e8e PHP \u5386\u4ee3\u5347\u7ea7\u4ee5\u6765\u575a\u5b88\u7684\u5411\u4e0b\u517c\u5bb9\u6027\uff0c\u81f3\u4eca\u8fd8\u53ef\u4ee5\u770b\u5230\u4e0d\u5c11\u7528\u300c\u5f53\u5e74\u7684\u300d\u539f\u751f\u51fd\u6570\u5199\u51fa\u6765\u7684\u4ea7\u54c1\u4ee3\u7801\u53ef\u4ee5\u8fd0\u884c\uff0c\u900f\u8fc7\u547d\u540d\u89c4\u5219\u6211\u4eec\u4e5f\u53ef\u4ee5\u770b\u51fa\u5f53\u5e74\u7684 PHP\uff0c\u597d\u50cf\u7684\u786e\u300c\u4e0d\u591f\u5b8c\u5584\u300d\u3002\n \u5728\u56fd\u7f51\u3001\u516c\u5b89\u90fd\u5f00\u59cb\u987a\u7740\u52bf\u5934\u6570\u5b57\u5316\uff0c\u5efa\u7acb\u5185\u90e8\u4e13\u7f51\uff0c\u63d0\u5021\u4fe1\u606f\u5316\u529e\u516c\u7684\u96f6\u51e0\u5e74\uff0c\u6025\u9700\u8981\u4e00\u6279\u201c\u4e13\u4e1a\u7a0b\u5e8f\u5458\u201d\u5f00\u53d1\u5404\u7c7b\u201c\u4e13\u4e1a\u5316\u201d\u7684\u7cfb\u7edf\u3002\u800c\u5728\u90a3\u4e2a\u5e74\u4ee3\uff1aPHP \u7684\u786e\u300c\u5341\u5206\u8f7b\u91cf\u300d\uff1bNginx \u8fd8\u6ca1\u6709\u8bde\u751f\uff1b\u56fd\u5185 C++ \u51e0\u4e4e\u662f\u6e05\u4e00\u8272\u7684 VC6\uff0c\u5b66\u4e60\u3001\u5f00\u53d1\u96be\u5ea6\u90fd\u5f88\u5927\uff1b\u6240\u4ee5\uff0cJAVA \u6210\u4e86\u4e0d\u4e8c\u4e4b\u9009\u3002\n \u800c\u90a3\u4e5f\u662f JAVA \u6700\u76db\u884c\u7684\u5e74\u4ee3\u5427\uff0c\u5f53\u7136\uff0c\u540e\u6765\u5b89\u5353\u673a\u7684\u7206\u53d1\u53c8\u7ed9\u4e86 JAVA \u7b2c\u4e8c\u6b21\u84ec\u52c3\u53d1\u5c55\u7684\u673a\u4f1a\u3002\n \u800c\u73b0\u5982\u4eca\uff0cPHP \u4e00\u4e2a\u63a5\u4e00\u4e2a\u7684\u65b0\u7279\u6027\u3001\u65b0\u6846\u67b6\u6211\u60f3\u4e0d\u5fc5\u518d\u591a\u5217\u4e3e\u3002\u90a3\u4e9b\u5f53\u5e74\u5f00\u53d1\u8fd9\u7c7b\u7cfb\u7edf\u7684\u7a0b\u5e8f\u5458\uff0c\u591a\u6570\u5df2\u7ecf\u8fc8\u5165 40+ \u7684\u6b65\u4f10\uff0c\u6ca1\u6709\u8db3\u591f\u7684\u52a8\u529b\u518d\u53bb\u5b66\u4e60\u65e5\u65b0\u6708\u5f02\u7684\u65b0\u6280\u672f\uff1b\u81f3\u4e8e\u5728\u516c\u53f8\u5e26\u51fa\u6765\u7684\u65b0\u4eba\uff0c\u81ea\u7136\u4e5f\u662f\u9009\u7528\u6b64\u7c7b\u6280\u672f\u6808\u3002\u4ee5\u81f3\u4e8e\u76ee\u524d\u5185\u7f51\u5e94\u7528\uff0c\u7edd\u5927\u591a\u6570\u4f9d\u7136\u662f JAVA \u7684\u5929\u4e0b\u3002\n\u76ee\u524d\u5609\u5174\u7684 IT \u884c\u4e1a\u73af\u5883\uff0c\u6211\u60f3\u5927\u5bb6\u5e94\u8be5\u90fd\u61c2\u3002\u5927\u6279\u7684\u4e00\u7ebf\u57ce\u5e02\u7a0b\u5e8f\u5458\u56de\u5230\u81ea\u5df1\u7684\u8001\u5bb6\uff0c\u800c\u5584\u4e8e\u94bb\u7814\u3001\u6bd4\u8f83\u4f18\u79c0\u7684\u5e74\u8f7b\u4eba\u591a\u6570\u6d41\u5931\u5230\u4e86\u4e0a\u676d\u3002\u56e0\u6b64\u9020\u6210\u4e00\u79cd\u73b0\u72b6\uff1a\u6211\u4eec\u7684\u6280\u672f\u6808\uff0c\u5927\u5927\u843d\u540e\u4e8e\u5730\u7406\u8ddd\u79bb\u4ec5 100 \u516c\u91cc\u5916\u7684\u4e0a\u6d77\u3002\n\u56e2\u961f \u5bf9\u4e8e PHP \u6765\u8bf4\uff0c\u867d\u7136\u7ecf\u5386\u4e86\u4e00\u6b21\u53c8\u4e00\u6b21\u7684\u5347\u7ea7\uff0c\u4f46\u5b83\u7b80\u5355\u6613\u5b66\u3001\u90e8\u7f72\u5feb\u6377\u7684\u7279\u6027\u5e76\u6ca1\u6709\u56e0\u6b64\u51cf\u5f31\u3002\n\u5bf9\u4e8e\u56e2\u961f\u6765\u8bf4\uff0c\u82e5\u662f\u9009\u62e9 JAVA\uff0c\u6216\u8bb8\u6211\u53ef\u4ee5\u62db\u5230\u4e00\u5927\u6279\u4ece\u5b66\u6821\u8bfe\u7a0b\u5b66\u51fa\u6765\u7684 JAVA \u7a0b\u5e8f\u5458\uff0c\u7b80\u5386\u4e0a\u5982\u51fa\u4e00\u8f99\u7684\u300c\u7cbe\u901a C\u3001C++\u3001JAVA\u300d\uff0c\u4f46\u4ed6\u4eec\u771f\u7684\u70ed\u7231\u6280\u672f\u5417\uff1f\u771f\u7684\u559c\u6b22\u63a2\u7a76\u5417\uff1f\u771f\u7684\u80fd\u4e3b\u52a8\u625b\u8d77\u8d23\u4efb\u5417\uff1f\u771f\u7684\u80fd\u505a\u51fa\u6709\u7075\u9b42\u7684\u4ea7\u54c1\u5417\uff1f\n\u6216\u8bb8\uff0c\u5728\u4e8c\u4e09\u7ebf\u57ce\u5e02\u770b\u8d77\u6765\u300c\u53e6\u7c7b\u300d\u7684\u8bed\u8a00\uff08PHP\uff09\u548c\u6846\u67b6\uff08Laravel\uff09\uff0c\u53cd\u800c\u80fd\u591f\u5e2e\u6211\u7b5b\u9009\u51fa\u4e00\u6279\u4e0d\u9519\u7684\u4eba\u9009\u3002\n\u6ca1\u6709\u6700\u597d\uff0c\u53ea\u6709\u6700\u5408\u9002 \u4e16\u754c\u4e0a\u4efb\u4f55\u4e8b\u7269\u90fd\u4e0d\u4f1a\u662f\u5b8c\u7f8e\u7684\uff0c\u8bed\u8a00\u4e5f\u4e00\u6837\u3002\u867d\u7136\u6709\u4eba\u558a\u7740\u300cPHP \u662f\u4e16\u754c\u4e0a\u6700\u597d\u7684\u8bed\u8a00\u300d\uff0c\u6211\u5374\u4ece\u4e0d\u8ba4\u4e3a\u4f1a\u6709\u4efb\u4f55\u4e00\u79cd\u8bed\u8a00\u80fd\u5e94\u5bf9\u6240\u6709\u573a\u666f\u3002\u5c31\u50cf\u524d\u51e0\u5e74\u7684\u5927\u524d\u7aef\u98ce\u6f6e\uff0c\u9ad8\u547c\u300cJS \u5927\u4e00\u7edf\u300d\u7684\u4eba\uff0c\u73b0\u5728\u53bb\u54ea\u4e86\uff1f\nPHP \u5728\u591a\u6570\u7f51\u9875\u540e\u7aef\u7684\u5f00\u53d1\u53ef\u4ee5\u7b97\u5f97\u4e0a\u5982\u9c7c\u5f97\u6c34\uff0c\u800c\u624b\u673a\u7aef API \u7684\u5f00\u53d1\uff0c\u4e5f\u53ef\u4ee5\u79f0\u5f97\u4e0a\u5e94\u5bf9\u81ea\u5982\uff0c\u4f46\u5b83\u540c\u6837\u5b58\u5728\u7f3a\u9677\u3002\n\u6709\u4eba\u4f1a\u6293\u4f4f\u8fd9\u4e9b\u5f31\u70b9\u4e0d\u653e\uff0c\u4f46\u6211\u53ea\u60f3\u8bf4\uff1a\n PHP\uff0c\u4f60\u5c31\u53ea\u505a\u597d\u591a\u6570\u60c5\u51b5\u7684\u5e38\u89c1\u540e\u7aef\u5f00\u53d1\u573a\u666f\u5c31\u591f\u4e86\uff0c\u6211\u4eec\u4e0d\u9700\u8981\u4f60\u5168\u80fd\uff0c\u4f46\u4f60\u8981\u505a\u7cbe\uff0c\u505a\u5f3a\u3002\n  \u4f60\u4e0d\u64c5\u957f\u7684\u9ad8\u5e76\u53d1\u3001\u591a\u7ebf\u7a0b\u3001Socket\uff0c\u6709\u6210\u5343\u4e0a\u4e07\u66f4\u5b8c\u7f8e\u7684\u89e3\u51b3\u65b9\u6848\uff0cNode.js \/ Golang \/ .NET Core\uff0c\u8d1f\u8f7d\u5747\u8861\u3001\u4efb\u52a1\u961f\u5217\u3001Swoole\u2026\u2026\n \u66f4\u4f55\u51b5\uff0c\u5bf9\u4e8e\u653f\u52a1\u90e8\u95e8\u6765\u8bf4\uff0c\u9700\u8981\u505a\u5230\u591a\u5927\u624d\u4f1a\u9047\u89c1\u5982\u4e0a\u573a\u666f\uff1f\u800c\u6709\u4ec0\u4e48\u662f\u591a\u4e70\u53f0\u670d\u52a1\u5668\u89e3\u51b3\u4e0d\u6389\u7684\u5462\uff1f\n \u5982\u679c\u6709\uff0c\u90a3\u5c31\u4e24\u53f0\u3002\n END \u6211\u770b\u597d PHP \u5728\u7f51\u9875\u540e\u7aef\u9886\u57df\u7684\u53d1\u5c55\u524d\u666f\uff0c\u6211\u76f8\u4fe1\u5b83\u662f\u8db3\u4ee5\u5e94\u5bf9\uff0c\u751a\u81f3\u7ef0\u7ef0\u6709\u4f59\u7684\u3002\n\u6700\u540e\u7559\u7ed9\u5927\u5bb6\u4e00\u4e2a\u95ee\u9898\uff1a\u4e3a\u4ec0\u4e48\u672c\u7bc7\u6587\u7ae0\u6700\u521d\u5c31\u6ca1\u6709\u9009\u62e9\u4ece\u6280\u672f\u89d2\u5ea6\u53bb\u8003\u91cf\u5bf9\u6bd4\uff1f\n\u6b22\u8fce\u5927\u4f6c\u4ea4\u6d41\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/why-php-in-2017\/","summary":"\u5728\u5404\u7c7b\u4ea4\u6d41\u7fa4\uff0c\u751a\u81f3\u591a\u6570\u8001\u4e00\u8f88\u7a0b\u5e8f\u5458\u7684\u773c\u91cc\uff0c\u8ba4\u4e3a PHP \u662f\u300c\u8f7b\u91cf\u7684\u300d\u3001\u300c\u4e0d\u5b8c\u5584\u7684\u300d\u3001\u300c\u6027\u80fd\u96be\u4ee5\u4f18\u5316\u300d\u7684\uff0c\u800c\u8fd9\u4e48\u591a\u5e74\u6765\u4e00\u76f4\u575a\u633a\u7684 Java \u5374\u6210\u4e86\u5f00\u53d1\u300cXX \u7cfb\u7edf\u300d\u7684\u540e\u7aef\u9996\u9009\u8bed\u8a00\u3002\u4e3a\u6b64\uff0c\u672c\u7bc7\u6587\u7ae0\u5c06\u5c3d\u91cf\u4ece\u975e\u6280\u672f\u89d2\u5ea6\u544a\u8bc9\u5927\u5bb6\uff1aWhy PHP\uff1f\n \u73b0\u72b6 \u5176\u5b9e\uff0c\u4ece Java \u548c PHP \u7684\u5386\u53f2\u4e0d\u96be\u770b\u51fa\u3002\u5728 Java \u5f00\u59cb\u76db\u884c\u7684\u5e74\u4ee3\uff0cPHP \u8fd8\u662f\u4e2a\u201c\u6bdb\u5934\u5c0f\u5b50\u201d\uff0c\u53ea\u662f\u4e2a\u666e\u666e\u901a\u901a\u7684\u811a\u672c\u8bed\u8a00\u7f62\u4e86\uff0c\u751a\u81f3\u8fde\u9762\u5411\u5bf9\u8c61\u7684\u57fa\u672c\u6982\u5ff5\u2014\u2014\u7c7b\uff0c\u90fd\u6ca1\u6709\u652f\u6301\u3002\n \u9274\u4e8e PHP \u5386\u4ee3\u5347\u7ea7\u4ee5\u6765\u575a\u5b88\u7684\u5411\u4e0b\u517c\u5bb9\u6027\uff0c\u81f3\u4eca\u8fd8\u53ef\u4ee5\u770b\u5230\u4e0d\u5c11\u7528\u300c\u5f53\u5e74\u7684\u300d\u539f\u751f\u51fd\u6570\u5199\u51fa\u6765\u7684\u4ea7\u54c1\u4ee3\u7801\u53ef\u4ee5\u8fd0\u884c\uff0c\u900f\u8fc7\u547d\u540d\u89c4\u5219\u6211\u4eec\u4e5f\u53ef\u4ee5\u770b\u51fa\u5f53\u5e74\u7684 PHP\uff0c\u597d\u50cf\u7684\u786e\u300c\u4e0d\u591f\u5b8c\u5584\u300d\u3002","title":"Why PHP\uff1f\u6d45\u8c08\u9009\u62e9 PHP \u4f5c\u4e3a\u540e\u7aef\u4e3b\u529b\u5f00\u53d1\u8bed\u8a00\u7684\u539f\u56e0"},{"content":"Windows \u7cfb\u7edf\u53ef\u4ee5\u4f7f\u7528\u4fee\u6539\u6ce8\u518c\u8868\u7684\u65b9\u5f0f\u5b9e\u73b0\u53f3\u952e\u5728\u5f53\u524d\u76ee\u5f55\u6253\u5f00\u547d\u4ee4\u884c\uff0c\u90a3\u4e48 macOS \u8be5\u5982\u4f55\u4f18\u96c5\u5730\u5b9e\u73b0\u8fd9\u4e00\u529f\u80fd\u5462\uff1f\n1. \u6309\u7167\u5982\u4e0b\u8def\u5f84\u627e\u5230\u8bbe\u7f6e\uff1a \u7cfb\u7edf\u4e0e\u504f\u597d\u8bbe\u7f6e -&gt; \u952e\u76d8 -&gt; \u5feb\u6377\u952e -&gt; \u670d\u52a1 -&gt; \u65b0\u5efa\u4f4d\u4e8e\u6587\u4ef6\u5939\u4f4d\u7f6e\u7684\u7ec8\u7aef\u7a97\u53e3 \/ \u6807\u7b7e\u9875\n2. \u9009\u4e2d\u590d\u9009\u6846\uff0c\u5e76\u5728\u53f3\u4fa7\u8bbe\u7f6e\u5feb\u6377\u952e\u3002 \u8fd9\u91cc\u6211\u8bbe\u7f6e\u4e3a\uff1aCommand + -\n3. \u6d4b\u8bd5\u6548\u679c\u3002 ","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-start-terminal-in-finder-menu\/","summary":"Windows \u7cfb\u7edf\u53ef\u4ee5\u4f7f\u7528\u4fee\u6539\u6ce8\u518c\u8868\u7684\u65b9\u5f0f\u5b9e\u73b0\u53f3\u952e\u5728\u5f53\u524d\u76ee\u5f55\u6253\u5f00\u547d\u4ee4\u884c\uff0c\u90a3\u4e48 macOS \u8be5\u5982\u4f55\u4f18\u96c5\u5730\u5b9e\u73b0\u8fd9\u4e00\u529f\u80fd\u5462\uff1f\n1. \u6309\u7167\u5982\u4e0b\u8def\u5f84\u627e\u5230\u8bbe\u7f6e\uff1a \u7cfb\u7edf\u4e0e\u504f\u597d\u8bbe\u7f6e -&gt; \u952e\u76d8 -&gt; \u5feb\u6377\u952e -&gt; \u670d\u52a1 -&gt; \u65b0\u5efa\u4f4d\u4e8e\u6587\u4ef6\u5939\u4f4d\u7f6e\u7684\u7ec8\u7aef\u7a97\u53e3 \/ \u6807\u7b7e\u9875\n2. \u9009\u4e2d\u590d\u9009\u6846\uff0c\u5e76\u5728\u53f3\u4fa7\u8bbe\u7f6e\u5feb\u6377\u952e\u3002 \u8fd9\u91cc\u6211\u8bbe\u7f6e\u4e3a\uff1aCommand + -","title":"macOS Finder \u53f3\u952e\u542f\u52a8\u7ec8\u7aef\uff08Terminal\uff09"},{"content":" \u6b63\u5219\u8868\u8fbe\u5f0f(regular expression)\u63cf\u8ff0\u4e86\u4e00\u79cd\u5b57\u7b26\u4e32\u5339\u914d\u7684\u6a21\u5f0f\uff08pattern\uff09\uff0c\u53ef\u4ee5\u7528\u6765\u68c0\u67e5\u4e00\u4e2a\u4e32\u662f\u5426\u542b\u6709\u67d0\u79cd\u5b50\u4e32\u3001\u5c06\u5339\u914d\u7684\u5b50\u4e32\u66ff\u6362\u6216\u8005\u4ece\u67d0\u4e2a\u4e32\u4e2d\u53d6\u51fa\u7b26\u5408\u67d0\u4e2a\u6761\u4ef6\u7684\u5b50\u4e32\u7b49\u3002\u2014\u2014 \u83dc\u9e1f\u6559\u7a0b\n [*] Part 1  \u662f\u4ec0\u4e48\uff1f \u7528\u9014\uff1f\uff08\u641c\u7d22\u3001\u66ff\u6362\u3001\u63d0\u53d6\u3001\u9a8c\u8bc1\u3001\u683c\u5f0f\u5316\u3001Rewrite \u7b49\uff09 \u600e\u4e48\u7528\uff1f \u5e38\u89c1\u6b63\u5219\u5f15\u64ce\uff08PCRE \/ DEELX &hellip;\uff09\u3002 \u5e38\u89c1\u6b63\u5219\u6d4b\u8bd5\u5de5\u5177\uff08Deelx Regex Match Tracer \/ Regex 101 \/ RegExr \/ Cyrilex \/ For PHPer: PHP Live Regex\uff09 \u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\uff08.*\uff09\u3002 \u4f18\u7f3a\u70b9\u3002  [*] Part 2  \u5e38\u89c1\u5143\u5b57\u7b26\uff1a., \\d, \\w, \\b, \\s \u5e38\u89c1\u9650\u5b9a\u7b26\uff1a*, ?, +, {min,max}  [ ] Part 3  \u5143\u5b57\u7b26\uff1a[], [^], ^, $, \\u \u5206\u5272\u7b26\uff1a| \u5b50\u8868\u8fbe\u5f0f\uff1a()  [ ] Part 4  \u8d2a\u5a6a\u5339\u914d \u61d2\u60f0\u5339\u914d  [ ] Part 5  \u975e\u6355\u83b7\u5143\u5b57\u7b26 \u53cd\u5411\u5f15\u7528  ","permalink":"https:\/\/wi1dcard.dev\/posts\/regex-classes\/","summary":"\u6b63\u5219\u8868\u8fbe\u5f0f(regular expression)\u63cf\u8ff0\u4e86\u4e00\u79cd\u5b57\u7b26\u4e32\u5339\u914d\u7684\u6a21\u5f0f\uff08pattern\uff09\uff0c\u53ef\u4ee5\u7528\u6765\u68c0\u67e5\u4e00\u4e2a\u4e32\u662f\u5426\u542b\u6709\u67d0\u79cd\u5b50\u4e32\u3001\u5c06\u5339\u914d\u7684\u5b50\u4e32\u66ff\u6362\u6216\u8005\u4ece\u67d0\u4e2a\u4e32\u4e2d\u53d6\u51fa\u7b26\u5408\u67d0\u4e2a\u6761\u4ef6\u7684\u5b50\u4e32\u7b49\u3002\u2014\u2014 \u83dc\u9e1f\u6559\u7a0b\n [*] Part 1  \u662f\u4ec0\u4e48\uff1f \u7528\u9014\uff1f\uff08\u641c\u7d22\u3001\u66ff\u6362\u3001\u63d0\u53d6\u3001\u9a8c\u8bc1\u3001\u683c\u5f0f\u5316\u3001Rewrite \u7b49\uff09 \u600e\u4e48\u7528\uff1f \u5e38\u89c1\u6b63\u5219\u5f15\u64ce\uff08PCRE \/ DEELX &hellip;\uff09\u3002 \u5e38\u89c1\u6b63\u5219\u6d4b\u8bd5\u5de5\u5177\uff08Deelx Regex Match Tracer \/ Regex 101 \/ RegExr \/ Cyrilex \/ For PHPer: PHP Live Regex\uff09 \u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\uff08.","title":"\u6b63\u5219\u8868\u8fbe\u5f0f\u8bfe\u7a0b\u5927\u7eb2"},{"content":"\u56e0\u9879\u76ee\u9700\u8981\uff0c\u8981\u4f7f\u7528 Laravel \u8fde\u63a5\u5fae\u8f6f\u7684 SQL Server\uff0c\u867d\u7136\u8fd9\u79cd\u7ec4\u5408\u663e\u5f97\u975e\u5e38\u5947\u8469\uff0c\u4f46\u7ecf\u8fc7\u6d4b\u8bd5\u8fd8\u662f\u53ef\u4ee5\u6210\u529f\u5b9e\u73b0\u7684\u3002\n\u51c6\u5907 \u9996\u5148\uff0c\u56e0\u4e3a Laravel \u8fde\u63a5\u6570\u636e\u5e93\u9ed8\u8ba4\u662f\u4f7f\u7528 PDO \u6269\u5c55\uff0c\u800c PDO \u8fde\u63a5 SQL Server \u9700\u8981\u4f7f\u7528 pdo_dblib \u6269\u5c55\uff0c\u6240\u4ee5\u9996\u5148\u7b2c\u4e00\u6b65\u5c31\u662f\u5b89\u88c5\u6b64\u6269\u5c55\u3002\nMAC \u7cfb\u7edf \u76f4\u63a5\u4f7f\u7528 brew \u547d\u4ee4\u5b89\u88c5\u5373\u53ef\u3002\n\u5b89\u88c5\u5b8c\u6210\u4e0d\u8981\u5fd8\u8bb0valet restart\u3002\n\u7fa4\u6656 NAS \u6253\u5f00 WebStation\uff0c\u5207\u6362\u5230 PHP \u8bbe\u7f6e\u9875\u9762\uff0c\u9009\u4e2d pdo_dblib \u6269\u5c55\uff0c\u5e94\u7528\u5373\u53ef\u3002\n\u4e2a\u4eba\u611f\u89c9\uff0c\u7fa4\u6656 WebStation \u505a\u5f97\u8fd8\u662f\u86ee\u65b9\u4fbf\u7684\u3002\n\u5f00\u59cb laravel new\u521b\u5efa\u9879\u76ee\uff0claravel 5.5 \u5728config\/database.php\u81ea\u5e26 sqlsrv \u7684\u914d\u7f6e\u6a21\u677f\uff0c\u56e0\u6b64\u5224\u5b9a\u5e94\u8be5\u80fd\u591f\u76f4\u63a5\u652f\u6301\uff0c\u4e0d\u9700\u8981\u7b2c\u4e09\u65b9\u6269\u5c55\u5305\u3002\n\u4fee\u6539.env\u914d\u7f6e\u5982\u4e0b\uff1a\nDB_CONNECTION=sqlsrv DB_HOST=\u670d\u52a1\u5668\u5730\u5740 DB_PORT=\u670d\u52a1\u5668\u7aef\u53e3 DB_DATABASE=\u6570\u636e\u5e93\u540d DB_USERNAME=\u7528\u6237\u540d DB_PASSWORD=\u5bc6\u7801  \u89c1\u6548 \u4fee\u6539routes\/web.php\u6587\u4ef6\uff0c\u4f7f\u7528 DB Facade \u76f4\u63a5\u8fd0\u884c\u67e5\u8be2\u5e76\u6253\u5370\uff1a\nRoute::get('\/', function () { dd(DB::select('select * from he_Building')); });  \u8fd0\u884c\uff1a\nDONE\uff01\n\u540e\u7eed\u95ee\u9898 \u5173\u4e8e\u4e2d\u6587\u4e71\u7801\u95ee\u9898\uff0c\u4e24\u7bc7\u8f83\u6709\u4ef7\u503c\u53c2\u8003\u6587\u7ae0\uff1a\nPHP \u5728\u7c7b Unix \u73af\u5883\u4e0b\u4f7f\u7528 PDO \u8fde\u63a5 SQL Server \u7684\u95ee\u9898\nphp \u4f7f\u7528 dblib \u6269\u5c55,\u8fde\u63a5 sqlserver \u4e2d\u6587\u4e71\u7801\u95ee\u9898\n","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-work-with-sql-server\/","summary":"\u56e0\u9879\u76ee\u9700\u8981\uff0c\u8981\u4f7f\u7528 Laravel \u8fde\u63a5\u5fae\u8f6f\u7684 SQL Server\uff0c\u867d\u7136\u8fd9\u79cd\u7ec4\u5408\u663e\u5f97\u975e\u5e38\u5947\u8469\uff0c\u4f46\u7ecf\u8fc7\u6d4b\u8bd5\u8fd8\u662f\u53ef\u4ee5\u6210\u529f\u5b9e\u73b0\u7684\u3002\n\u51c6\u5907 \u9996\u5148\uff0c\u56e0\u4e3a Laravel \u8fde\u63a5\u6570\u636e\u5e93\u9ed8\u8ba4\u662f\u4f7f\u7528 PDO \u6269\u5c55\uff0c\u800c PDO \u8fde\u63a5 SQL Server \u9700\u8981\u4f7f\u7528 pdo_dblib \u6269\u5c55\uff0c\u6240\u4ee5\u9996\u5148\u7b2c\u4e00\u6b65\u5c31\u662f\u5b89\u88c5\u6b64\u6269\u5c55\u3002\nMAC \u7cfb\u7edf \u76f4\u63a5\u4f7f\u7528 brew \u547d\u4ee4\u5b89\u88c5\u5373\u53ef\u3002","title":"Laravel 5.5 \u8fde\u63a5 MS SQL\uff08SQL Server\uff09\u6570\u636e\u5e93"},{"content":"\u4eca\u65e5\u6280\u672f\u535a\u5ba2 POST \u8bf7\u6c42\u51fa\u73b0\u56de\u6e90\u5f02\u5e38\u8d85\u65f6\u95ee\u9898\uff0c\u7ecf\u591a\u65b9\u9762\u6392\u67e5\uff0c\u5148\u540e\u6392\u9664 PHP-FPM \u6162\u6267\u884c\u3001MySQL \u6162\u67e5\u8be2\u3001HTTPS \u534f\u8bae\u6545\u969c\u3001\u672c\u5730\u7f51\u7edc\u6545\u969c\u7b49\u95ee\u9898\u540e\u53d1\u73b0\u76f4\u63a5\u8bbf\u95ee\u6e90\u7ad9\u6b63\u5e38\uff0c\u6545\u6000\u7591 CDN \u95ee\u9898\uff0c\u968f\u5373\u63d0\u4ea4\u5de5\u5355\u5e76\u591a\u6b21\u7535\u8054\u817e\u8baf\u4e91\u50ac\u4fc3\uff0c\u6700\u7ec8\u5f97\u5230\u7b54\u590d\u3002\n2017-10-27 15:00 \u6545\u969c\u53d1\u751f\uff0c\u9996\u5148\u6000\u7591\u7ad9\u70b9\u95ee\u9898\uff08\u8bfb\u53d6\u8bf7\u6c42\u6b63\u5e38\uff0c\u5199\u5165\u51fa\u9519\uff09\u3002\n2017-10-27 17:00 \u6392\u67e5\u53d1\u73b0\u95ee\u9898\u539f\u56e0\u662f\u817e\u8baf\u4e91 CDN \u56de\u6e90\u6545\u969c\uff0c\u6b64\u65f6\u5168\u7ad9 GET \u8bf7\u6c42\u6b63\u5e38\uff0cPOST \u8bf7\u6c42 HTTP \u534f\u8bae\u51fa\u73b0 CONNECTION RESET\uff0cHTTPS \u8fd4\u56de 564\uff08\u6839\u636e\u817e\u8baf\u5148\u524d\u89e3\u91ca\u4e3a\u56de\u6e90\u8d85\u65f6\uff09\uff0c\u90e8\u5206\u529f\u80fd\u53ef\u80fd\u51fa\u73b0\u95ee\u9898\uff0c\u63d0\u4ea4\u5de5\u5355\u7b49\u5f85\u817e\u8baf\u4fee\u590d\u3002\n2017-10-27 17:45 \u7535\u8054\u817e\u8baf\u4e91 400\uff0c\u8981\u6c42\u5c3d\u5feb\u7b54\u590d\u3002 2017-10-27 18:00 \u66f4\u6362\u7f51\u7edc\u73af\u5883\uff0c\u7ecf\u6d4b\u8bd5\u53d1\u73b0\u6d59\u6c5f\u7535\u4fe1\u95ee\u9898\u5b58\u5728\uff0c\u6d59\u6c5f\u79fb\u52a8\u6b63\u5e38\u3002\n2017-10-27 18:50 \u6545\u969c\u6062\u590d\uff0c\u4f46\u4f9d\u65e7\u672a\u7b49\u5230\u817e\u8baf\u4e91\u7ed9\u4e88\u7b54\u590d\uff0c\u751a\u81f3\u6ca1\u6709\u91cd\u73b0\u95ee\u9898\u3002\n2017-10-27 19:00 \u6536\u5230\u817e\u8baf\u4e91\u65b9\u9762\u6d4b\u8bd5\u5de5\u7a0b\u5e08\u7b54\u590d\uff1a\u94fe\u8def\u5df2\u7ecf\u6062\u590d\u3002 2017-10-27 19:35 \u6536\u5230\u6545\u969c\u8be6\u60c5\u8bf4\u660e\uff0c\u5982\u4e0b\uff1a\n \u60a8\u597d\uff0ccdn \u76d1\u63a7\u53d1\u73b0\u9488\u5bf9\u5f02\u5730\u8986\u76d6\u7684\u90e8\u5206\u5730\u533a\/\u8fd0\u8425\u5546\u5b58\u56de\u6e90\u94fe\u8def\u52ab\u6301\u60c5\u51b5\uff0c\u5bf9 post \u8bf7\u6c42\u652f\u6301\u5f02\u5e38\uff0c\u76d1\u63a7\u53d1\u73b0\u540e\uff0c\u5df2\u7ecf\u4eba\u5de5\u5e72\u9884\u4ecb\u5165\u8c03\u5ea6\uff0c\u8c03\u6574\u56de\u6e90\u94fe\u8def\uff0c\u76ee\u524d\u95ee\u9898\u5df2\u7ecf\u6062\u590d\u3002\u540c\u65f6\uff0c\u52ab\u6301\u95ee\u9898\u5df2\u7ecf\u62a5\u969c\u8fd0\u8425\u5546\u5904\u7406\u4e2d\u3002\u7ed9\u60a8\u5e26\u6765\u4e0d\u4fbf\u5341\u5206\u62b1\u6b49\u3002\n ","permalink":"https:\/\/wi1dcard.dev\/posts\/qcloud-cdn-breakdown\/","summary":"\u4eca\u65e5\u6280\u672f\u535a\u5ba2 POST \u8bf7\u6c42\u51fa\u73b0\u56de\u6e90\u5f02\u5e38\u8d85\u65f6\u95ee\u9898\uff0c\u7ecf\u591a\u65b9\u9762\u6392\u67e5\uff0c\u5148\u540e\u6392\u9664 PHP-FPM \u6162\u6267\u884c\u3001MySQL \u6162\u67e5\u8be2\u3001HTTPS \u534f\u8bae\u6545\u969c\u3001\u672c\u5730\u7f51\u7edc\u6545\u969c\u7b49\u95ee\u9898\u540e\u53d1\u73b0\u76f4\u63a5\u8bbf\u95ee\u6e90\u7ad9\u6b63\u5e38\uff0c\u6545\u6000\u7591 CDN \u95ee\u9898\uff0c\u968f\u5373\u63d0\u4ea4\u5de5\u5355\u5e76\u591a\u6b21\u7535\u8054\u817e\u8baf\u4e91\u50ac\u4fc3\uff0c\u6700\u7ec8\u5f97\u5230\u7b54\u590d\u3002\n2017-10-27 15:00 \u6545\u969c\u53d1\u751f\uff0c\u9996\u5148\u6000\u7591\u7ad9\u70b9\u95ee\u9898\uff08\u8bfb\u53d6\u8bf7\u6c42\u6b63\u5e38\uff0c\u5199\u5165\u51fa\u9519\uff09\u3002\n2017-10-27 17:00 \u6392\u67e5\u53d1\u73b0\u95ee\u9898\u539f\u56e0\u662f\u817e\u8baf\u4e91 CDN \u56de\u6e90\u6545\u969c\uff0c\u6b64\u65f6\u5168\u7ad9 GET \u8bf7\u6c42\u6b63\u5e38\uff0cPOST \u8bf7\u6c42 HTTP \u534f\u8bae\u51fa\u73b0 CONNECTION RESET\uff0cHTTPS \u8fd4\u56de 564\uff08\u6839\u636e\u817e\u8baf\u5148\u524d\u89e3\u91ca\u4e3a\u56de\u6e90\u8d85\u65f6\uff09\uff0c\u90e8\u5206\u529f\u80fd\u53ef\u80fd\u51fa\u73b0\u95ee\u9898\uff0c\u63d0\u4ea4\u5de5\u5355\u7b49\u5f85\u817e\u8baf\u4fee\u590d\u3002","title":"2017-10-27 \u817e\u8baf\u4e91 CDN \u6545\u969c\u8bb0\u5f55"},{"content":" \u6ca1\u9519\u53c8\u8e29\u5751\u4e86\u3002\n\u56e0\u9879\u76ee\u9700\u8981\u4e0e DZ \u8bba\u575b\u5b9e\u73b0 SSO \u767b\u5f55\u3001\u8d26\u53f7\u540c\u6b65\u7b49\u529f\u80fd\uff0c\u7ecf\u8001\u53f8\u673a\u6ce2\u6ce2\u63a8\u8350\uff0c\u76f4\u63a5\u4f7f\u7528 DZ \u5b98\u65b9\u4ea7\u54c1 UCenter \u96c6\u6210\u5373\u53ef\uff1b\u4e8e\u662f\u9648\u665f&amp;\u6f58\u662d\u5b87\u6298\u817e\u4e86\u4e00\u5929 UCenter\uff0c\u53ef\u8fd8\u662f\u9047\u5230\u4e86\u8fc7\u4e0d\u53bb\u7684\u201c\u62e6\u8def\u864e\u201d\uff0c\u4e8e\u662f\u63a5\u8fd1\u4e0b\u73ed\u4e4b\u9645\uff0c\u51b3\u5b9a\u63a5\u624b\u8fd9\u4e2a\u95ee\u9898\uff0c\u4e0d\u77e5\u4e0d\u89c9\u8e0f\u4e0a\u4e86\u8fc7\u8282\u4f9d\u65e7\u52a0\u73ed\u7684\u4e0d\u5f52\u8def\u3002\n UCenter UCenter \u662f\u539f DZ \u56e2\u961f\uff08\u73b0\u5df2\u88ab\u817e\u8baf\u6536\u8d2d\uff09\u5f00\u53d1\u7684\u4e00\u5957\u7edf\u4e00\u8ba4\u8bc1\u7cfb\u7edf\uff08\u987e\u540d\u601d\u4e49\uff1aUser Center\uff09\uff0c\u5177\u4f53\u4ecb\u7ecd\u53c2\u89c1\uff1a\u767e\u5ea6\u767e\u79d1\u3002\u8fd9\u5957\u4ea7\u54c1\u5df2\u7ecf\u975e\u5e38\u6709\u5e74\u5934\uff0c\u4ee5\u73b0\u5728\u7684\u773c\u5149\u518d\u6765\u5ba1\u89c6\u5f53\u65f6\u7684\u67b6\u6784\u786e\u5b9e\u5b58\u5728\u4e0d\u5c11\u95ee\u9898\uff0c\u5f53\u7136\uff0c\u8fd9\u5e76\u4e0d\u5f71\u54cd\u5b83\u5177\u6709\u5386\u53f2\u4ef7\u503c\u3002\n\u5148\u6765\u8bf4\u4e0b UCenter\uff08\u4e0b\u79f0UC\uff09\u7684\u5927\u81f4\u67b6\u6784\u5427\uff0c\u8fd9\u662f\u5751\u8e29\u5b8c\u4e4b\u540e\u603b\u7ed3\u51fa\u6765\u7684\uff0c\u4e3a\u4e86\u4e0d\u5f71\u54cd\u540e\u7eed\u7406\u89e3\u6240\u4ee5\u63d0\u524d\u4ecb\u7ecd\u3002\n UC \u6709\u4e24\u7aef\uff1aserver \/ client\uff1b\n\u5176\u4e2d\uff0cserver \u7aef\u7ef4\u62a4\u4e00\u5957\u81ea\u6709\u7684\u8868\u7ed3\u6784\uff0c\u5e76\u63d0\u4f9b http api\uff1b\n\u800c\u591a\u4e2a\u7531\u7528\u6237\uff08\u8fd9\u91cc\u6307\u57fa\u4e8e uc \u7684\u4e8c\u6b21\u5f00\u53d1\u4eba\u5458\uff09\u5b9e\u73b0\u7684 client \u7aef\uff0c\u901a\u8fc7\u8c03\u7528 client sdk\uff0c\u53ef\u5b9e\u73b0\u76f4\u63a5\u64cd\u4f5c server \u7aef\u6570\u636e\u5e93\u6216\u8c03\u7528 http api \u6765\u5199\u5165\u3001\u8bfb\u53d6 user \u6570\u636e\uff0c\u4ece\u800c\u5b9e\u73b0\u591a client \u7aef\u7ef4\u62a4\u540c\u4e00\u4efd user \u6570\u636e\u526f\u672c\u3002\n \u90a3\u4e48\uff0c\u5bf9\u4e8e\u73b0\u6709\u7684\u5e94\u7528\uff08client\uff09\uff0c\u5982\u4f55\u96c6\u6210\u5230 UC \u800c\u4e0d\u9700\u8981\u4fee\u6539\u8868\u7ed3\u6784\u5462\uff1f\n UC \u63d0\u4f9b\u4e86\u4e00\u5957 Server&ndash;&gt;Client \u7c7b\u4f3c\u201c\u56de\u8c03\u201d\u7684\u673a\u5236\uff0c\u6211\u4eec\u53ea\u8981\u53c2\u7167\u5176 client \u7aef\u4f8b\u5b50\u7f16\u5199\u597d\u7b26\u5408\u5176\u89c4\u8303\u7684 client\uff0c\u90a3\u4e48 server \u7aef\u5373\u53ef\u5728\u6536\u5230\u5176\u4ed6 client \u5199\u5e93\u8bf7\u6c42\u65f6\uff0c\u901a\u77e5\u672c client\uff1b\u6211\u4eec\u53ea\u8981\u54cd\u5e94\u6765\u81ea server \u7aef\u7684\u8bf7\u6c42\uff0c\u5c06\u7528\u6237\u5199\u5165\u539f\u6709\u903b\u8f91\u6570\u636e\u5e93\u5373\u53ef\u3002\n\u8fd9\u6837\u5373\u53ef\u5b9e\u73b0\u4e0d\u4fee\u6539\u539f\u6709\u5e94\u7528\u6570\u636e\u5e93\uff0c\u4e24\u5957\u5e93\u201c\u540c\u6b65\u201d\u7684\u72b6\u6001\u3002\n \u8e29\u5751 \u4f5c\u4e3a\u4e00\u6b3e\u76f8\u5f53\u6709\u5386\u53f2\uff0c\u4e14\u5176\u56e2\u961f\u8fd1\u4e4e\u653e\u5f03\u7ef4\u62a4\u7684\u4ea7\u54c1\uff0c\u907f\u514d\u4e0d\u4e86\u6709\u95ee\u9898\u3002\n\u7ecf\u8fc7\u6d4b\u8bd5\uff0cclient&ndash;&gt;server \u662f\u6ca1\u6709\u95ee\u9898\u7684\uff0c\u6309\u7167\u6587\u6863\uff08advanced\/document\uff09\u5c06 uc_client \u76ee\u5f55\uff08\u6b64\u76ee\u5f55\u5373\u4e3a client \u7aef sdk\uff09\u590d\u5236\u5230 examples \u6587\u4ef6\u5939\u4e0b\uff0c\u5e76\u914d\u7f6e\u597d server \u548c client \u540e\uff0cclient \u7aef demo \u53ef\u4ee5\u6b63\u5e38\u67e5 user\u3001\u5199 user\u3002\n\u53e6\u5916\uff0c\u8fd9\u91cc\u8981\u6ce8\u610f\u4ee5\u4e0b\u4e24\u4e2a\u5e38\u91cf\u7684\u8bbe\u7f6e\uff0c\u5c24\u5176\u662f\u540e\u8005\uff1a\ndefine('UC_CONNECT', 'NULL'); \/\/ \u8fde\u63a5 UCenter \u7684\u65b9\u5f0f: mysql\/NULL, \u9ed8\u8ba4\u4e3a\u7a7a\u65f6\u4e3a fscoketopen() define('UC_API', 'http:\/\/111.*.*.107\/uc_server'); \/\/ UCenter \u7684 URL \u5730\u5740, \u5728\u8c03\u7528\u5934\u50cf\u65f6\u4f9d\u8d56\u6b64\u5e38\u91cf  \u5728 UC_CONNECT \u4e3a NULL \u65f6\uff0cclient-sdk \u4f1a\u901a\u8fc7 http post \u65b9\u5f0f\u4e0e server \u7aef\u901a\u8baf\uff0c\u6b64\u65f6 http \u8bf7\u6c42\u7684\u5730\u5740\u4f9d\u8d56\u4e8e UC_API \u5e38\u91cf\u3002\n\u586b\u5751 \u4f46\uff0c\u95ee\u9898\u5c31\u51fa\u5728 client \u7aef\u63a5\u6536 server \u7aef\u56de\u8c03\u7684\u4f8b\u5b50\u4e0a\u3002\n\u6839\u636e\u6587\u6863\uff0c\u6b64\u4f8b\u5b50\u4f4d\u4e8e\uff1aadvanced\/examples\/api\/uc.php\uff0c\u9042\u6253\u5f00\u6b64\u6587\u4ef6\uff0c\u4e4d\u4e00\u770b 300+\u884c\u4ee3\u7801\u6709\u70b9\u5934\u5927\uff0c\u4e0d\u8fc7\u8010\u5fc3\u89c2\u5bdf\u8fd8\u662f\u80fd\u6478\u5230\u95e8\u9053\u7684\u3002\n\u6b64\u6587\u4ef6\u5927\u6982\u5206\u4e3a 4 \u90e8\u5206\uff1a\n \u5e38\u91cf\u5b9a\u4e49 \u4e3b\u7a0b\u5e8f uc_note \u7c7b\u5b9a\u4e49\uff08\u56de\u8c03 API \u7684\u529f\u80fd\u5b9e\u73b0\u5c31\u5728\u8fd9\u91cc\uff09 \u4e00\u4e9b\u8f85\u52a9\u51fd\u6570  \u6253\u5f00 UC \u670d\u52a1\u7aef\uff0c\u914d\u7f6e\u597d\u53c2\u6570\u540e\u63d0\u793a\u901a\u8baf\u5931\u8d25\uff0c\u540e\u63d0\u793a\u201c\u6b63\u5728\u8fde\u63a5&hellip;\u201d\u5c31\u6ca1\u6709\u540e\u7eed\u53cd\u5e94\uff1b\u6839\u636e\u7f51\u4e0a\u7684\u6559\u7a0b\u627e\u5230\u8c03\u7528 uc.php \u7684\u5177\u4f53\u53c2\u6570\u503c\uff0c\u5e26\u53c2\u6570\u8fd0\u884c\u6b64\u6587\u4ef6\uff0c\u62a5\u9519 500\u3002\n\u7531\u6b64\u53ef\u4ee5\u57fa\u672c\u786e\u5b9a\u662f\u4ee3\u7801\u5b58\u5728\u95ee\u9898\uff0c\u4e8e\u662f\u6253\u5f00 php \u7684\u62a5\u9519\u663e\u793a\uff0c\u5e76\u5c06 error_reporting \u8bbe\u7f6e\u4e3a E_ALL\uff0c\u67e5\u770b\u5177\u4f53\u9519\u8bef\u51fa\u73b0\u5728\u4ec0\u4e48\u4f4d\u7f6e\u3002\n\u9996\u5148\uff0c\u63d0\u793aset_magic_quotes_runtime\u51fd\u6570\u4e0d\u5b58\u5728\uff0c\u6545\u67e5\u8be2 php \u6587\u6863\uff0c\u53d1\u73b0\u4e00\u6761\u660e\u663e\u7684\u8b66\u544a\uff1a\n Warning: This function was DEPRECATED in PHP 5.3.0, and REMOVED as of PHP 7.0.0.\n \u95ee\u9898\u627e\u5230\uff0c\u968f\u5373\u5220\u9664\u6b64\u884c\u4ee3\u7801\u3002\u5728 PHP 5.3 \u5c31\u5df2\u7ecf\u88ab\u5f03\u7528\u7684\u51fd\u6570\uff0c\u5c45\u7136\u8fd8\u5199\u5728\u4f8b\u5b50\u4e2d\uff0c\u53ef\u89c1\u6b64\u4ea7\u54c1\u8fd8\u771f\u662f\u6709\u5e74\u5934\u3002\n\u7ee7\u7eed\u8fd0\u884c\uff0c\u4f9d\u65e7\u62a5\u9519\uff0c\u8fd9\u6b21\u7684\u9519\u8bef\u975e\u5e38\u5e38\u89c1\uff1amysql_connect\u51fd\u6570\u4e0d\u5b58\u5728\uff0c\u4e5f\u5c31\u662f\u8bf4\u4ee3\u7801\u91cc\u6709\u67d0\u4e2a\u5730\u65b9\u91c7\u7528\u4e86\u540c\u6837\u88ab\u5f03\u7528\u7684 mysql \u6269\u5c55\u2026\u2026\n\u7ecf\u8fc7\u641c\u7d22\uff0c\u53d1\u73b0\u662fadvanced\/examples\/include\/db_mysql.class.php\u5185\u91c7\u7528\u4e86 mysql \u7cfb\u5217\u51fd\u6570\uff1b\u770b\u4e86\u4e0b\u4ee3\u7801\u91cf\u4e0d\u591a\uff0c\u5f53\u7136\u4e5f\u4e0d\u7b97\u5c11\uff0c\u4e8e\u662f\u8111\u6d77\u4e2d\u5192\u51fa\u4e00\u4e2a\u201c\u5077\u61d2\u201d\u7684\u60f3\u6cd5\u2014\u2014\u53bb dz \u6216\u8005 uc \u7684\u76ee\u5f55\u770b\u6709\u6ca1\u6709\u4f7f\u7528 mysqli\uff08PDO \u5c31\u752d\u60f3\u4e86&hellip;\uff09\u5b9e\u73b0\u7684 db_mysql \u7c7b\u6587\u4ef6\uff0c\u4e8e\u662f\u5168\u5c40\u641c\u7d22\uff0c\u679c\u7136\u627e\u5230\uff0c\u4e8c\u8bdd\u4e0d\u8bf4\u76f4\u63a5\u66ff\u6362\uff0c\u6b64\u62a5\u9519\u6d88\u5931\u3002\n \u6ce8\uff1a\u7531\u4e8e\u53ea\u662f\u6d4b\u8bd5\u6240\u7528\uff0c\u4e0d\u9700\u8981\u64cd\u4f5c\u6570\u636e\u5e93\uff0c\u6545\u4e0b\u65b9\u4fee\u6539\u7248 sdk \u5185\u7684 uc.php \u6ce8\u91ca\u6389\u4e86\u6570\u636e\u5e93\u8fde\u63a5\u4ee3\u7801\u3002\n \u4f46\u95ee\u9898\u4f9d\u65e7\u5b58\u5728\uff0c\u53c8\u4e00\u4e2a\u65b0\u7684\u9519\u8bef\u53d1\u751f\u3002\u8bf4\u5230\u8fd9\u91cc\u6211\u4e0d\u7981\u60f3\u8d77\u4e00\u4e2a\u6bb5\u5b50\uff1a\n\u80dc\u5229\u5728\u671b\uff0c\u63a5\u7740\u4fee bug\u3002\n\u8fd9\u6b21\u7684\u62a5\u9519\u662f\u8fd9\u4e00\u53e5\uff1a\nexit($uc_note-&gt;$get['action']($get, $post));  \u8fd9\u5c31\u6709\u70b9\u5947\u602a\u4e86\uff0c\u63d0\u793a\u65b9\u6cd5\u540d\uff08\u4e5f\u5c31\u662f$get[&lsquo;action&rsquo;]\u7684\u503c\uff09\u5fc5\u987b\u662f\u5b57\u7b26\u4e32\uff0c\u7ecf\u8fc7 var_dump \u9a8c\u8bc1\u7684\u786e\u4e3a\u5b57\u7b26\u4e32\uff0c\u9690\u7ea6\u8bb0\u5f97\u8c8c\u4f3c php7 \u5bf9\u4e8e\u52a8\u6001\u8c03\u7528\u51fd\u6570\u7684\u7279\u6027\u597d\u50cf\u8fdb\u884c\u4e86\u4fee\u6539\uff0c\u4e8e\u662f\u7ee7\u7eed google\uff0c\u53d1\u73b0\u6b64\u51fd\u6570\uff1acall_user_func\uff0c\u968f\u5373\u4fee\u6539\u4ee3\u7801\u4e3a\u5982\u4e0b\u5f62\u6001\uff1a\necho call_user_func([$uc_note, $get['action']], $get, $post); exit;  \u4e0e\u4fee\u6539\u524d\u4ee3\u7801\u9884\u671f\u540c\u7406\uff0c\u52a8\u6001\u8c03\u7528\u7c7b\u5b9e\u4f8b\u7684\u6210\u5458\u51fd\u6570\uff0c\u5177\u4f53\u7528\u6cd5\u8bf7\u53c2\u89c1\uff1acall_user_func\u3002\n\u4fee\u6539\u540e\u518d\u6b21\u8fd0\u884c\uff0c\u7ec8\u4e8e\u6210\u529f\u8fd4\u56de\u201c1\u201d\uff0cUC \u670d\u52a1\u7aef\u63d0\u793a\u901a\u4fe1\u6210\u529f\u3002\n\u81f3\u6b64\uff0cclient \u7aef\u4f8b\u5b50\u6210\u529f\u8fd0\u884c\u3002\n\u540e\u8bb0 \u9664\u4e86\u672c\u8eab\u7684 bug\uff0cuc \u63d0\u4f9b\u7684\u4f8b\u5b50\u6bd4\u8f83\u590d\u6742\uff0c\u611f\u89c9\u6709\u70b9\u7ed5\uff0c\u8fd8\u9700\u8981\u8f83\u5f3a\u7684 php \u529f\u5e95\u624d\u80fd\u7406\u6e05\u601d\u8def\uff0c\u8fd9\u5c31\u5bfc\u81f4\u4e86\u4e00\u6574\u5929\u7684\u8fd8\u662f\u6ca1\u6709\u641e\u5b9a\u7684\u5751&hellip;\n\u5bf9\u4e8e\u7b2c\u4e09\u65b9\u7684\u7ec4\u4ef6\u3001SDK\uff0c\u4e0d\u8981\u754f\u60e7\u4e8e\u770b\u6e90\u7801\uff0c\u521a\u5f00\u59cb\u9605\u8bfb\u53ef\u80fd\u6bd4\u8f83\u56f0\u96be\uff0c\u4f46\u4e07\u4e07\u4e0d\u80fd\u6d6e\u8e81\uff0c\u9759\u4e0b\u5fc3\u6765\u4e00\u884c\u4e00\u884c\u7406\u6e05\u601d\u8def\uff0c\u6ca1\u89c1\u8fc7\u7684\u591a\u8c37\u6b4c\uff0c\u5927\u90e8\u5206\u95ee\u9898\u90fd\u662f\u53ef\u4ee5\u9760\u81ea\u5df1\u89e3\u51b3\u7684\uff1b\u800c\u89e3\u51b3\u95ee\u9898\u7684\u8fc7\u7a0b\u7ed9\u81ea\u5df1\u5e26\u6765\u7684\u5b66\u4e60\u548c\u63d0\u5347\uff0c\u6bd4\u89e3\u51b3\u95ee\u9898\u672c\u8eab\u91cd\u8981\u7684\u591a\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/php7-ucenter-client-example-issue\/","summary":"\u6ca1\u9519\u53c8\u8e29\u5751\u4e86\u3002\n\u56e0\u9879\u76ee\u9700\u8981\u4e0e DZ \u8bba\u575b\u5b9e\u73b0 SSO \u767b\u5f55\u3001\u8d26\u53f7\u540c\u6b65\u7b49\u529f\u80fd\uff0c\u7ecf\u8001\u53f8\u673a\u6ce2\u6ce2\u63a8\u8350\uff0c\u76f4\u63a5\u4f7f\u7528 DZ \u5b98\u65b9\u4ea7\u54c1 UCenter \u96c6\u6210\u5373\u53ef\uff1b\u4e8e\u662f\u9648\u665f&amp;\u6f58\u662d\u5b87\u6298\u817e\u4e86\u4e00\u5929 UCenter\uff0c\u53ef\u8fd8\u662f\u9047\u5230\u4e86\u8fc7\u4e0d\u53bb\u7684\u201c\u62e6\u8def\u864e\u201d\uff0c\u4e8e\u662f\u63a5\u8fd1\u4e0b\u73ed\u4e4b\u9645\uff0c\u51b3\u5b9a\u63a5\u624b\u8fd9\u4e2a\u95ee\u9898\uff0c\u4e0d\u77e5\u4e0d\u89c9\u8e0f\u4e0a\u4e86\u8fc7\u8282\u4f9d\u65e7\u52a0\u73ed\u7684\u4e0d\u5f52\u8def\u3002\n UCenter UCenter \u662f\u539f DZ \u56e2\u961f\uff08\u73b0\u5df2\u88ab\u817e\u8baf\u6536\u8d2d\uff09\u5f00\u53d1\u7684\u4e00\u5957\u7edf\u4e00\u8ba4\u8bc1\u7cfb\u7edf\uff08\u987e\u540d\u601d\u4e49\uff1aUser Center\uff09\uff0c\u5177\u4f53\u4ecb\u7ecd\u53c2\u89c1\uff1a\u767e\u5ea6\u767e\u79d1\u3002\u8fd9\u5957\u4ea7\u54c1\u5df2\u7ecf\u975e\u5e38\u6709\u5e74\u5934\uff0c\u4ee5\u73b0\u5728\u7684\u773c\u5149\u518d\u6765\u5ba1\u89c6\u5f53\u65f6\u7684\u67b6\u6784\u786e\u5b9e\u5b58\u5728\u4e0d\u5c11\u95ee\u9898\uff0c\u5f53\u7136\uff0c\u8fd9\u5e76\u4e0d\u5f71\u54cd\u5b83\u5177\u6709\u5386\u53f2\u4ef7\u503c\u3002\n\u5148\u6765\u8bf4\u4e0b UCenter\uff08\u4e0b\u79f0UC\uff09\u7684\u5927\u81f4\u67b6\u6784\u5427\uff0c\u8fd9\u662f\u5751\u8e29\u5b8c\u4e4b\u540e\u603b\u7ed3\u51fa\u6765\u7684\uff0c\u4e3a\u4e86\u4e0d\u5f71\u54cd\u540e\u7eed\u7406\u89e3\u6240\u4ee5\u63d0\u524d\u4ecb\u7ecd\u3002","title":"UCenter 1.6 Client Example \u5bf9 PHP7 \u517c\u5bb9\u4e0d\u826f\u7684\u6392\u67e5\u4e0e\u4fee\u590d"},{"content":"\u524d\u8a00 \u6b64\u95ee\u9898\u4e8e2017\u5e749\u670829\u65e5\u53d1\u73b0\uff0c\u81f3\u4eca\uff082017\u5e7410\u670819\u65e5\uff09\u4e03\u725b\u6587\u6863\u4ecd\u672a\u8fdb\u884c\u4fee\u590d\uff0c\u6545\u53d1\u6b64\u6587\uff0c\u5e0c\u671b\u5f15\u8d77\u4e03\u725b\u5b98\u65b9\u91cd\u89c6\u3002\n\u524d\u4e9b\u65e5\u5b50\u9879\u76ee\u9700\u8981\uff0c\u7528\u4e0a\u4e03\u725b\u5bf9\u8c61\u5b58\u50a8\uff0c\u56e0\u4e4b\u524d\u90fd\u662f\u7528\u7684\u4f20\u7edf\u67b6\u6784\uff1a\n \u5ba2\u6237\u7aef -&gt; \u4e1a\u52a1\u670d\u52a1\u5668 -&gt; \u4e03\u725b\u4e91  \u8fd9\u6b21\u6253\u7b97\u6362\u4e00\u4e0b\uff0c\u5c1d\u8bd5\u66f4\u8282\u7701\u4e1a\u52a1\u670d\u52a1\u8d44\u6e90\u7684\u76f4\u4f20\u5bf9\u8c61\u5b58\u50a8\u65b9\u5f0f\uff1a\n \u5ba2\u6237\u7aef -&gt; \u4e1a\u52a1\u670d\u52a1\u5668\u62ff Token \u5ba2\u6237\u7aef -&gt; \u76f4\u4f20\u4e03\u725b\u4e91 \u4e03\u725b\u4e91 -&gt; \u56de\u8c03\u4e1a\u52a1\u670d\u52a1\u5668 HTTP API \u63a5\u53e3 \u4e1a\u52a1\u670d\u52a1\u5668\u6536\u5230\u4e0a\u4f20\u901a\u77e5, \u9a8c\u8bc1\u6765\u81ea\u4e03\u725b\u670d\u52a1\u5668 -&gt; done.  Just like this\uff1a\n\u8fc7\u7a0b \u7531\u6b64\uff0c\u8fc7\u7a0b\u4e2d\u6709\u5fc5\u4e0d\u53ef\u5c11\u7684\u4e00\u73af\uff1a\u9a8c\u8bc1\u56de\u8c03\u8bf7\u6c42\u662f\u6765\u81ea\u4e8e\u4e03\u725b\u7684\u670d\u52a1\u5668\uff0c\u800c\u4e0d\u662f\u5176\u4ed6\u7684\u4f2a\u88c5\uff0f\u6076\u610f\u8bf7\u6c42\u3002\n\u6545\u5bfb\u627e\u4e03\u725b\u6587\u6863\uff1a\n \u4e03\u725b\u4e91\u5bf9\u8c61\u5b58\u50a8 PHP SDK - \u573a\u666f\u5316\u5b9e\u4f8b \u4e03\u725b\u4e91\u5bf9\u8c61\u5b58\u50a8\u4ea7\u54c1\u624b\u518c - \u5b89\u5168\u673a\u5236 \u4e03\u725b\u4e91\u5bf9\u8c61\u5b58\u50a8\u4ea7\u54c1\u624b\u518c - \u4e0a\u4f20\u8d44\u6e90 - \u56de\u8c03\u901a\u77e5   \u7b2c\u4e00\u6761\u94fe\u63a5\u538b\u6839\u6ca1\u63d0\u5230\u9a8c\u8bc1\u56de\u8c03\u7684\u95ee\u9898\u3002\uff08\u96be\u9053\u4e03\u725b\u7684 PHP \u5de5\u7a0b\u5e08\u538b\u6839\u5ffd\u7565\u4e86\u8fd9\u4e2a\u5b89\u5168\u95ee\u9898\u4e48\uff1f\uff09 \u7b2c\u4e8c\u6761\u94fe\u63a5\u5185\u540c\u6837\u4e0d\u5b58\u5728\u76f8\u5173\u89e3\u7b54\u3002 \u7ec8\u4e8e\uff0c\u5728\u7b2c\u4e09\u6761\u94fe\u63a5\u7684\u672b\u5c3e\u627e\u5230\u4e86\u5173\u4e8e\u8fd9\u4e2a\u95ee\u9898\u7684\u89e3\u7b54\uff1a  \u201c\u503c\u5f97\u5e86\u5e78\u7684\u662f\u201d\uff0c\u6709 PHP \u7684\u4ee3\u7801\u5b9e\u73b0\u3002\n\u4f46\u6211\u4eec\u90a3\u65f6\u5019\u8fd8\u9ad8\u5174\u7684\u592a\u65e9\u4e86\u3002\n\u6392\u67e5 \u63a5\u4e0b\u6765\u6211\u4eec\u4f7f\u7528\u6b64\u51fd\u6570\u6765\u9a8c\u8bc1\u6743\u9650\uff0c\u4f46\u7ecf\u8fc7\u591a\u8f6e\u8c03\u8bd5\uff0c\u65e0\u8bba\u5982\u4f55\u90fd\u65e0\u6cd5\u9a8c\u8bc1\u901a\u8fc7\u3002\u6700\u5f00\u59cb\u6211\u4ee5\u4e3a\u662f\u6f58\u662d\u5b87\u4ee3\u7801\u6ca1\u6709\u8ba4\u771f\u770b\uff0c\u7c97\u5fc3\u5927\u610f\u5f15\u8d77\u7684\u9519\u8bef\uff0c\u4f46\u540e\u6765\u6211\u4eb2\u81ea\u770b\u4ee3\u7801\uff0c\u4e00\u6b65\u4e00\u6b65\u68c0\u67e5\u53ef\u80fd\u7684\u7f16\u7801\u95ee\u9898\u3001\u53c2\u6570\u95ee\u9898\uff0c\u751a\u81f3\u7528 Fiddler \u505a\u4ee3\u7406\u770b\u670d\u52a1\u5668\u53d1\u6765\u7684\u6570\u636e\u5305\u662f\u5426\u6b63\u5e38\u3001XDebug \u4e0b\u65ad\u4e00\u6b65\u4e00\u6b65\u8c03\u8bd5\uff0c\u6700\u7ec8\u53d1\u73b0\u7684\u786e\u662f\u6ca1\u95ee\u9898\u7684\u3002\n\u8fd9\u5c31\u5947\u4e86\u602a\u4e86\uff01\u4e3a\u4ec0\u4e48\u4f1a\u51fa\u9519\u5462\uff1f\n\u786e\u5b9a\u6211\u4eec\u7684\u7b97\u6cd5\u6ca1\u6709\u95ee\u9898\u540e\uff0c\u6211\u4eec\u51b3\u5b9a\u7ee7\u7eed\u7814\u7a76\u6587\u6863\uff0c\u56e0\u4e3a\u90a3\u4e2a\u65f6\u5019\u6211\u4eec\u8ba4\u4e3a\u8fd9\u6837\u7684\u5927\u5382\u66f4\u65b0\u4e86\u8fd9\u4e48\u4e45\u7684\u6587\u6863\uff0c\u600e\u4e48\u53ef\u80fd\u4f1a\u51fa\u95ee\u9898\u5462\uff0c\u6709\u5751\u7684\u8bdd\u6211\u4eec\u80af\u5b9a\u4e0d\u662f\u7b2c\u4e00\u4e2a\u8e29\u4e0b\u53bb\u7684\u4eba\u3002\n\u8ba4\u771f\u201c\u7814\u8bfb\u201d\u4e4b\u540e\uff0c\u6211\u4eec\u53d1\u73b0\uff1a\u5728\u5b89\u5168\u673a\u5236 - \u4e0a\u4f20\u7b56\u7565\u7684\u6587\u6863\u5185\uff0c\u5bf9callbackBody\u7684\u89e3\u91ca\u5982\u4e0b\uff1a\n \u4e0a\u4f20\u6210\u529f\u540e\uff0c\u4e03\u725b\u4e91\u5411\u4e1a\u52a1\u670d\u52a1\u5668\u53d1\u9001 Content-Type: application\/x-www-form-urlencoded \u7684 POST \u8bf7\u6c42\u3002\u8be5\u5b57\u6bb5 App-Server \u53ef\u4ee5\u901a\u8fc7\u76f4\u63a5\u8bfb\u53d6\u8bf7\u6c42\u7684 query \u6765\u83b7\u5f97\uff0c\u652f\u6301\u9b54\u6cd5\u53d8\u91cf\u548c\u81ea\u5b9a\u4e49\u53d8\u91cf\u3002callbackBody \u8981\u6c42\u662f\u5408\u6cd5\u7684 url query string\u3002\u5982\uff1akey=$(key)&amp;hash=$(etag)&amp;w=$(imageInfo.width)&amp;h=$(imageInfo.height)\u3002\n \u8fd9\u53e5\u8bdd\u6709\u70b9\u8ff7\uff0c\u6bd5\u7adf\u4e0b\u4e00\u884c\u7684callbackBodyType\u662f\u8fd9\u6837\u8bf4\u7684\uff1a\n \u4e0a\u4f20\u6210\u529f\u540e\uff0c\u4e03\u725b\u4e91\u5411\u4e1a\u52a1\u670d\u52a1\u5668\u53d1\u9001\u56de\u8c03\u901a\u77e5 callbackBody \u7684 Content-Type\u3002\u9ed8\u8ba4\u4e3a application\/x-www-form-urlencoded\uff0c\u4e5f\u53ef\u8bbe\u7f6e\u4e3a application\/json\u3002\n  callbackBody \u8981\u6c42\u662f\u5408\u6cd5\u7684 url query string \u4e5f\u53ef\u8bbe\u7f6e\u4e3aapplication\/json  \u6309\u7167\u6b63\u5e38\u601d\u7ef4\uff0c\u8fd9\u5e94\u8be5\u662f\u4e0d\u53d7\u5f71\u54cd\u7684\uff0c\u9ed8\u8ba4\u662f url query stirng\uff0c\u53ef\u4ee5\u6539\u4e3a json \u683c\u5f0f\u3002\u4f46\u8fd9\u4e24\u53e5\u76f8\u4e92\u6709\u6240\u51b2\u7a81\u7684\u63cf\u8ff0\u5f15\u8d77\u4e86\u6211\u4eec\u7684\u91cd\u89c6\uff0c\u9042\u5f00\u59cb\u52a8\u5de5\uff1a\u539f\u672c\u6211\u4eec\u4f7f\u7528\u7edf\u4e00\u7684 json \u683c\u5f0f\u4f5c\u4e3a callbackBody \u53d1\u9001\u5230\u4e1a\u52a1\u670d\u52a1\u5668\uff0c\u73b0\u5c1d\u8bd5\u6539\u4e3a query string \u6d4b\u8bd5\u770b\u4f1a\u4e0d\u4f1a\u6709\u95ee\u9898\u3002\n\u7ecf\u8fc7\u6d4b\u8bd5\uff0c\u4e03\u725b\u7684\u56de\u8c03\u901a\u8fc7\u4e86\u9a8c\u8bc1\u2026\u2026\n\u5f53\u65f6\u7684\u5fc3\u60c5\u2026\u2026!@#^@)##^@!@\n\u6211\u548c\u6f58\u662d\u5b87\u8c03\u4e86\u4e00\u6574\u5929\u7684\u95ee\u9898\uff0c\u5c45\u7136 TM \u662f\u56e0\u4e3a\u4e03\u725b\u7684\u9505\u3002\n\u89e3\u51b3 \u95ee\u9898\u627e\u5230\u4e86\uff0c\u63a5\u4e0b\u6765\u5c31\u8981\u89e3\u51b3\u3002\n\u9042\u63d0\u4ea4\u5de5\u5355\uff0c\u56e0\u4e3a\u5f53\u5929\u665a\u4e0a\u5df2\u7ecf\u6df1\u591c\uff0c\u6211\u4eec\u5de5\u5355\u63d0\u4ea4\u4e4b\u540e\u5c31\u5404\u81ea\u56de\u5bb6\u4e86\u3002\n\u7b2c\u4e8c\u5929\u5de5\u5355\u7684\u56de\u590d\uff0c\u4e0d\u51fa\u610f\u5916\u4e00\u6ce2\u4e09\u6298\u3002\n \u7ecf\u8fc7\u4e24\u5c0f\u65f6\u5f97\u5230\u7684\u7b54\u590d\uff1a\u662f\u5426\u5f97\u5230\u89e3\u51b3\uff1f \u518d\u6b21\u56de\u590d\u540e\uff0c\u5f97\u5230\u7684\u7b54\u590d\u662f\u6587\u6863\u663e\u800c\u6613\u89c1\u7684\uff0c\u7b54\u975e\u6240\u95ee\u3002\u7531\u6b64\u53ef\u89c1\uff1a\u4e03\u725b\u5ba2\u670d\u4eba\u5458\u6ca1\u6709\u3001\u6216\u662f\u6ca1\u6709\u8ba4\u771f\u9605\u8bfb\u6211\u5de5\u5355\u6700\u521d\u63d0\u51fa\u7684\u95ee\u9898\uff0c\u76f4\u63a5\u5306\u5fd9\u7ed9\u51fa\u4e86\u7b54\u590d\uff0c\u518d\u6b21\u62d6\u6162\u4e86\u6c9f\u901a\u6548\u7387\u3002 \u518d\u6b21\u56de\u590d\uff0c\u76f4\u63a5\u9644\u4e0a\u5b98\u65b9\u6587\u6863\u94fe\u63a5\uff0c\u4e3a\u4e86\u9632\u6b62\u4e0d\u8ba4\u8d26\u6211\u628a\u4ee3\u7801\u4e5f\u987a\u4fbf\u8d34\u4e86\u4e0a\u53bb\uff0c\u540c\u65f6\u628a\u6211\u4eec\u627e\u5230\u7684\u95ee\u9898\u5173\u952e\u70b9\uff1acallbackBodyType \u53c2\u6570\u4e5f\u4f5c\u4e86\u8bf4\u660e\u3002 \u7ec8\u4e8e\u5f97\u5230\u4e00\u7bc7\u770b\u8d77\u6765\u50cf\u662f\u6709\u6240\u7709\u76ee\u7684\u7b54\u590d\uff1a\u94fe\u63a5\uff0c\u53d1\u73b0\u4e00\u91cd\u8981\u7ebf\u7d22\uff1a\u5c45\u7136\u7528\u5230\u4e86$contentType\u53c2\u6570\uff0c\u8fd9\u4e0d\u5c31\u662f callbackBodyType \u5417\uff01\u867d\u7136\u6b64\u6587\u6863\u5185\u4ee3\u7801\u975e\u5e38\u201c\u7b80\u7565\u201d\uff0c\u5c31\u8fde$contentType\u90fd\u662f\u5199\u6b7b\u7684\uff0c\u4f46\u4e5f\u81f3\u5c11\u7ed9\u6211\u4eec\u63d0\u4f9b\u4e86\u89e3\u51b3\u601d\u8def\u3002 \u4e8e\u662f\uff0cgithub \u4e0b\u8f7d\u4e03\u725b PHP SDK \u6e90\u7801\uff0c\u679c\u7136 SDK \u5185\u6709\u6b64\u51fd\u6570\u5b9e\u73b0\u3002\u800c\u4ee5\u4e0a\u5217\u4e3e\u7684\u4e09\u7bc7\u6587\u6863\u5185\u5374\u4ece\u672a\u770b\u5230\u4e00\u5904\u63d0\u53ca\u3002 \u8fc7\u4e86\u4e00\u4f1a\u4e03\u725b\u5b98\u65b9\u53d1\u6765 github \u94fe\u63a5\uff0c\u867d\u7136\u5df2\u7ecf\u6ca1\u4ec0\u4e48\u5375\u7528\u3002  \u9898\u5916\u8bdd \u5f88\u5de7\u7684\u662f\uff0c\u7b2c\u4e8c\u5929\u6709\u4e2a\u5546\u52a1\u4eba\u5458\u8054\u7cfb\u6211\uff08\u4f01\u4e1a\u8d26\u53f7\u521a\u6ce8\u518c\u6ca1\u591a\u4e45\uff09\uff0c\u7b80\u76f4\u6c42\u4e4b\u4e0d\u5f97\u554a\uff01\u5de5\u5355\u6c9f\u901a\u6210\u672c\u592a\u5927\uff0c\u6211\u9a6c\u4e0a\u63d0\u51fa\u5b89\u6392\u51e0\u4e2a\u6280\u672f\u4eba\u5458\u62c9\u4e86\u4e00\u4e2a\u7fa4\u4e00\u8d77\u6765\u63a2\u8ba8\u8fd9\u4e2a\u95ee\u9898\u3002\n\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u82b1\u4e86\u5927\u6982\u534a\u4e2a\u5c0f\u65f6\u7684\u65f6\u95f4\u548c\u4ed6\u4eec\u89e3\u91ca\u5f53\u524d\u7684\u60c5\u51b5\u662f\u600e\u6837\u7684\uff0c\u4f46\u662f\u8c8c\u4f3c\u5bf9\u65b9\u5e76\u4e0d\u662f\u201c\u771f\u6b63\u7684\u201d\u540e\u7aef\u6280\u672f\u4eba\u5458\uff0c\u4e5f\u8054\u7cfb\u4e0d\u5230\u6280\u672f\u4eba\u5458\uff0c\u6240\u4ee5\u4e5f\u6ca1\u8d77\u5230\u4ec0\u4e48\u4f5c\u7528\u3002\n\u4e0d\u8fc7\u503c\u5f97\u80af\u5b9a\u7684\u662f\uff0c\u5bf9\u65b9\u6001\u5ea6\u662f\u975e\u5e38\u4e0d\u9519\u7684\uff0c\u79ef\u6781\u914d\u5408\u89e3\u51b3\u3002\nFinally em&hellip;\n\u95ee\u9898\u5706\u6ee1\u89e3\u51b3\uff0c\u503c\u5f97\u80af\u5b9a\u7684\u662f\uff0c\u89e3\u51b3\u95ee\u9898\u7684\u6001\u5ea6\u8fd8\u7b97\u6ee1\u610f\uff0c\u65e0\u8bba\u662f\u7535\u8bdd\u8054\u7cfb\u7684\u5546\u52a1\uff0c\u8fd8\u662f\u5de5\u5355\uff0c\u5747\u53cd\u590d\u627f\u8bfa\u5c3d\u5feb\u5b8c\u5584\uff0c\u5de5\u5355\u4e0a\u7684\u7b54\u590d\u751a\u81f3\u662f\u5df2\u7ecf\u5728\u6574\u7406\u6587\u6863\u5e76\u4e14\u8fdb\u884c\u4fee\u6539\u3002\u4e8e\u662f\u6211\u4eec\u4e5f\u5c31\u5f97\u8fc7\u4e14\u8fc7\uff0c\u7ee7\u7eed\u5fd9\u5176\u4ed6\u7684\u4e1c\u897f\u3002\n\u7136\u800c\u4eca\u5929\uff082017-10-19\uff09\u548c\u6f58\u662d\u5b87\u5076\u7136\u804a\u8d77\u6765\uff1a\n \u201c\u8bdd\u8bf4\u6700\u8fd1\u8981\u5f00\u65b0\u9879\u76ee\u4e86\uff0c\u4e0d\u77e5\u9053\u4e03\u725b\u90a3\u8fb9\u6587\u6863\u6709\u6ca1\u6709\u66f4\u65b0\uff1f\u4e4b\u524d\u8c03\u4e86\u90a3\u4e48\u4e45\u7684\u5751\u3002\u201d \u201c\u4e0d\u77e5\u9053\u554a\uff0c\u6211\u770b\u770b\u201d\u2026\u2026 \u201cem&hellip; \u8c8c\u4f3c&hellip; \u6ca1\u6709\u2026\u2026\u201d \u3002\u3002\u3002  \u4e0d\u77e5\u9053\u4e03\u725b\u5b98\u65b9\u53e3\u4e2d\u7684\u5c3d\u5feb\u662f 20+\u5929\uff1f\u8fd8\u662f\u6280\u672f\u4eba\u5458\u6574\u7406\u6587\u6863\u6574\u7406\u4e86\u51e0\u4e2a\u5468\u8fd8\u6ca1\u5199\u5b8c\u3002\n\u5e55\u540e\u7684\u539f\u56e0\u6211\u4eec\u4e0d\u5f97\u800c\u77e5\uff0c\u5927\u6982\u662f\u6211\u4eec\u8fd9\u79cd\u521b\u4e1a\u5c0f\u516c\u53f8\u9047\u5230\u7684\u95ee\u9898\uff0cdalao \u4eec\u4e5f\u4e0d\u4f1a\u653e\u5728\u773c\u91cc\u5427\u3002\n\u5f03\u5751\uff0c\u4e0b\u4e2a\u9879\u76ee\u6362\u53c8\u62cd\u4e91\u3002\n\u786c\u5e7f\uff1aCAREERS\n","permalink":"https:\/\/wi1dcard.dev\/posts\/qiniu-document-issue\/","summary":"\u524d\u8a00 \u6b64\u95ee\u9898\u4e8e2017\u5e749\u670829\u65e5\u53d1\u73b0\uff0c\u81f3\u4eca\uff082017\u5e7410\u670819\u65e5\uff09\u4e03\u725b\u6587\u6863\u4ecd\u672a\u8fdb\u884c\u4fee\u590d\uff0c\u6545\u53d1\u6b64\u6587\uff0c\u5e0c\u671b\u5f15\u8d77\u4e03\u725b\u5b98\u65b9\u91cd\u89c6\u3002\n\u524d\u4e9b\u65e5\u5b50\u9879\u76ee\u9700\u8981\uff0c\u7528\u4e0a\u4e03\u725b\u5bf9\u8c61\u5b58\u50a8\uff0c\u56e0\u4e4b\u524d\u90fd\u662f\u7528\u7684\u4f20\u7edf\u67b6\u6784\uff1a\n \u5ba2\u6237\u7aef -&gt; \u4e1a\u52a1\u670d\u52a1\u5668 -&gt; \u4e03\u725b\u4e91  \u8fd9\u6b21\u6253\u7b97\u6362\u4e00\u4e0b\uff0c\u5c1d\u8bd5\u66f4\u8282\u7701\u4e1a\u52a1\u670d\u52a1\u8d44\u6e90\u7684\u76f4\u4f20\u5bf9\u8c61\u5b58\u50a8\u65b9\u5f0f\uff1a\n \u5ba2\u6237\u7aef -&gt; \u4e1a\u52a1\u670d\u52a1\u5668\u62ff Token \u5ba2\u6237\u7aef -&gt; \u76f4\u4f20\u4e03\u725b\u4e91 \u4e03\u725b\u4e91 -&gt; \u56de\u8c03\u4e1a\u52a1\u670d\u52a1\u5668 HTTP API \u63a5\u53e3 \u4e1a\u52a1\u670d\u52a1\u5668\u6536\u5230\u4e0a\u4f20\u901a\u77e5, \u9a8c\u8bc1\u6765\u81ea\u4e03\u725b\u670d\u52a1\u5668 -&gt; done.","title":"\u4e03\u725b\u6587\u6863\u586b\u5751\u8fc7\u7a0b\u56de\u987e"},{"content":"0x00 \u524d\u8a00 \u66fe\u7ecf\u548c\u4e00\u4f4d\u4e0d\u505a\u6280\u672f\u3001\u4f46\u4e0e\u6280\u672f\u4eba\u5458\u6709\u5408\u4f5c\u7684\u670b\u53cb\u804a\u5929\uff0c\u4ed6\u4f5c\u4e3a\u4e00\u540d\u5c0f\u9886\u5bfc\uff0c\u5e38\u548c\u5916\u5305\u7a0b\u5e8f\u5458\u6253\u4ea4\u9053\u3002\u6211\u95ee\u4ed6\uff1a\u4f60\u89c9\u5f97\u505a\u7a0b\u5e8f\u5458\u6700\u5fcc\u8bb3\u4ec0\u4e48\uff1f\u4ed6\u7684\u56de\u7b54\u662f\uff1a\n \u4e0d\u8981\u8ba9\u8111\u888b\u91cc\u53ea\u5269\u4e0b\u662f\u4e0e\u975e\u3001\u96f6\u548c\u4e00\u3002\n\u4f5c\u8005\uff1a\u5b59\u4f1f\u5586\uff0f2017-10-15\n 0x01 \u95ee\u9898 \u90a3\u65f6\u5019\u4e0d\u61c2\u8fd9\u53e5\u8bdd\u7684\u6211\u4e00\u5fc3\u53ea\u987e\u94bb\u7814\u6280\u672f\uff0c\u4e8e\u662f\u8ffd\u95ee\uff1a\u4f55\u51fa\u6b64\u8a00\uff1f\n \u597d\u591a\u7a0b\u5e8f\u5458\u505a\u4e45\u4e86\u6280\u672f\uff0c\u4e60\u60ef\u4e86\u9762\u5bf9\u4ee3\u7801\uff0c\u6709\u65f6\u5019\u53ef\u4ee5\u660e\u663e\u611f\u89c9\u5230\u4ed6\uff08\u4eec\uff09\u7f3a\u4e4f\u4e86\u4e00\u4e9b\u57fa\u672c\u7684\u611f\u6027\u601d\u7ef4\u3002\u6bd4\u65b9\u8bf4\uff0c\u5ba2\u6237\u63d0\u51fa\u7684\u9700\u6c42\uff0c\u7ed9\u51fa\u7684\u7b54\u590d\u603b\u662f\uff1a\u6211\u53ea\u60f3\u8981\u4f60\u660e\u786e\u7684\u903b\u8f91\uff0c\u4e0d\u8981\u8ddf\u6211\u8bb2\u592a\u591a\uff1b\u53c8\u6216\u662f\u5bf9\u4e8e\u4ea7\u54c1\u7ecf\u7406\u53e3\u4e2d\u7684\u67d0\u4e2a\u6548\u679c\uff0c\u53ea\u6709\u4e24\u6761\u8def\uff1a\u53ef\u4ee5\u5b9e\u73b0\uff0f\u5b9e\u73b0\u4e0d\u4e86\uff1b\u8fd9\u8ba9\u6211\u96be\u4ee5\u63a5\u53d7\u3002\n \u662f\u554a\uff01\u4e16\u754c\u4e0a\u7684\u4e8b\u60c5\u600e\u4e48\u4f1a\u6709\u660e\u786e\u7684\u5206\u754c\u7ebf\uff0c\u4eba\u7684\u601d\u7ef4\u662f\u66f2\u7ebf\u7684\uff0c\u6700\u6015\u601d\u7ef4\u56fa\u5316\u3001\u4e00\u6839\u7b4b\u3002\n0x02 \u5206\u6790 \u56de\u5230\u670b\u53cb\u63d0\u51fa\u7684\u4e24\u4e2a\u4f8b\u5b50\uff1a\n\u5ba2\u6237\u6784\u60f3\u7684\u9700\u6c42  \u9996\u5148\u8981\u660e\u767d\uff0c\u5ba2\u6237\u662f\u666e\u901a\u4eba\uff0c\u4e0d\u61c2\u4ee3\u7801\u3002 \u5176\u6b21\uff0c\u5ba2\u6237\u63d0\u51fa\u7684\u9700\u6c42\u6c38\u8fdc\u53ea\u662f\u8111\u888b\u4e2d\u7684\u6784\u60f3\uff0c\u5982\u4f55\u628a\u6784\u60f3\u53d8\u6210\u73b0\u5b9e\u662f\u4f60\u7684\u4e8b\u60c5\uff0c\u800c\u4e0d\u662f\u5ba2\u6237\u9700\u8981\u601d\u8003\u7684\u4e1c\u897f\u3002 \u4f5c\u4e3a\u4e59\u65b9\uff0c\u6211\u4eec\u5e94\u8be5\u4e3b\u52a8\u534f\u52a9\u4e0d\u61c2\u4ee3\u7801\u7684\u201c\u5c0f\u767d\u201d\u5ba2\u6237\u786e\u5b9a\u4ed6\u60f3\u8981\u7684\u662f\u4ec0\u4e48\uff0c\u5ba2\u6237\u601d\u7ef4\u6240\u53ca\u53ea\u80fd\u505c\u7559\u5728\u4e0e\u6280\u672f\u65e0\u5173\u7684\u5c42\u6b21\u4e0a\uff0c\u90a3\u4e48\u63a5\u4e0b\u6765\u5c31\u9700\u8981\u4f60\u5e26\u9886\u5ba2\u6237\u53bb\u5206\u6790\uff0c\u7406\u6e05\u4ed6\u7684\u903b\u8f91\uff0c\u540c\u65f6\u4e5f\u8981\u601d\u8003\u5728\u6280\u672f\u5c42\u9762\u4e0a\u5982\u4f55\u5b9e\u73b0\u3002\u5ba2\u6237\u4e0d\u4e86\u89e3\u5728\u8f6f\u4ef6\u884c\u4e1a\u6b64\u7c7b\u201c\u6784\u60f3\u201d\u662f\u5982\u4f55\u5b9e\u73b0\uff0c\u800c\u6211\u4eec\u4e0d\u61c2\u5ba2\u6237\u884c\u4e1a\u5185\u7684\u89c4\u5219\uff0c\u5728\u4f60\u4e3b\u52a8\u5e26\u9886\u5ba2\u6237\u5206\u6790\u9700\u6c42\u3001\u5bf9\u9700\u6c42\u201c\u5177\u4f53\u5316\u201d\u7684\u65f6\u5019\uff0c\u5ba2\u6237\u53ef\u4ee5\u8ddf\u5f97\u4e0a\u4f60\u7684\u601d\u7ef4\uff0c\u53ca\u65f6\u4fee\u6b63\u4f60\u6240\u8bf4\u7684\u662f\u5426\u6709\u6240\u504f\u5dee\uff0c\u751a\u81f3\u6709\u53ef\u80fd\u6253\u5f00\u4e86\u601d\u8def\uff0c\u4e3b\u52a8\u8bf4\u51fa\u67d0\u4e00\u6a21\u5757\u7684\u7ec6\u8282\uff1b\u800c\u8fd9\u65f6\u5019\uff0c\u75af\u72c2\u7684\u8bb0\u7b14\u8bb0\u5c31\u597d\u4e86\u3002  \u5173\u4e8e\u4e0a\u9762\u8fd9\u6761\u7406\u8bba\uff0c\u6709\u4e2a\u5f88\u5178\u578b\u53c8\u7c7b\u4f3c\u7684\u4f8b\u5b50\uff1a\n People don&rsquo;t know what they want until you show it to them. - Steve Jobs\n\u6d88\u8d39\u8005\u5e76\u4e0d\u77e5\u9053\u81ea\u5df1\u60f3\u8981\u4ec0\u4e48\uff0c\u76f4\u5230\u6211\u4eec\u62ff\u51fa\u81ea\u5df1\u7684\u4ea7\u54c1\u3002\u2014\u2014\u53f2\u8482\u592b\u00b7\u4e54\u5e03\u65af\n \u6709\u5174\u8da3\u53ef\u4ee5\u770b\u770b\u300a\u4e54\u5e03\u65af\u4f20\u300b\u3002\n\u4e0a\u7ea7\u5e03\u7f6e\u7684\u4efb\u52a1  \u9886\u5bfc\u8981\u4ec0\u4e48\uff1f\u7ed3\u679c\u3002 \u9886\u5bfc\u8981\u4f60\u5e72\u4ec0\u4e48\uff1f\u5b9e\u73b0\u7ed3\u679c\u7684\u8fc7\u7a0b\u3002  \u5e38\u6709\u4eba\u548c\u6211\u8bf4\uff1a\u6211\u5df2\u7ecf\u5c3d\u529b\u4e86\u554a\uff0c\u4f46\u662f\u6709\u65f6\u5019\u6211\u771f\u7684\u4e0d\u4f1a\uff0c\u771f\u7684\u5b8c\u4e0d\u6210\uff0c\u4ed6\uff08Boss\uff09\u600e\u4e48\u8fd8\u662f\u8bad\u6211\u3002\n\u7684\u786e\uff0c\u505a\u5f00\u53d1\u96be\u514d\u9047\u5230\u5b9e\u5728\u89e3\u51b3\u4e0d\u6389\u7684\u201c\u5751\u201d\uff0c\u4f46\u4f60\u6709\u6ca1\u6709\u60f3\u8fc7\u662f\u81ea\u5df1\u7684\u95ee\u9898\uff1f\u6211\u4eec\u4e0d\u59a8\u6362\u4e2a\u89d2\u5ea6\uff0c\u7528\u533b\u751f\u548c\u75c5\u4eba\u6765\u63cf\u8ff0\u8fd9\u4ef6\u4e8b\u3002\n \u5047\u8bbe\u4f60\u662f\u4e00\u540d\u60a3\u8005\uff0c\u6765\u533b\u9662\u7ecf\u8fc7\u4e00\u7cfb\u5217\u7684\u8bca\u65ad\uff0c\u533b\u751f\u53ea\u544a\u8bc9\u4f60\uff1a\u4f60\u6ca1\u6551\u4e86\u3002\u4f60\u4f1a\u8f6c\u5934\u5c31\u8d70\uff0c\u653e\u5f03\u6cbb\u7597\u4e48\uff1f\n\u540c\u6837\uff0c\u8001\u677f\u5b89\u6392\u4f60\u53bb\u505a\u4e00\u4ef6\u4e8b\u60c5\uff0c\u4f60\u9047\u5230\u95ee\u9898\u53ea\u53cd\u9988\u4e00\u53e5\uff1a\u8fd9\u4e2a\u6211\u4eec\u505a\u4e0d\u4e86\u3002\u90a3\u8001\u677f\u662f\u4e0d\u662f\u4e5f\u8be5\u53cd\u95ee\u4e00\u53e5\uff1a\u6240\u4ee5\u6211\u4eec\u8fd9\u4e2a\u9879\u76ee\u5c31\u8fd9\u6837\u4e0d\u505a\u4e86\uff1f\n\u4f5c\u4e3a\u60a3\u8005\uff0c\u4f60\u4e00\u5b9a\u4f1a\u7ee7\u7eed\u8ffd\u95ee\uff1a\u4e3a\u4ec0\u4e48\u6ca1\u6551\u4e86\uff1f\u533b\u751f\u505a\u4e86\u54ea\u4e9b\u8bca\u65ad\uff1f\u6709\u6ca1\u6709\u5176\u4ed6\u65b9\u6848\u53ef\u4ee5\u7f13\u89e3\uff1f\u2026\u2026\n\u800c\u4f5c\u4e3a\u533b\u751f\uff0c\u4e5f\u540c\u6837\u6709\u4e49\u52a1\u63d0\u4f9b\u5b8c\u5584\u7684\u8bca\u65ad\u62a5\u544a\uff0c\u81f3\u5c11\u8ba9\u4e0d\u61c2\u533b\u5b66\u7684\u4f60\uff0c\u77e5\u9053\u81ea\u5df1\u8eab\u4f53\u662f\u54ea\u91cc\u51fa\u4e86\u6bdb\u75c5\u3002\n \u56de\u5230\u73b0\u5b9e\u3002\n\u8001\u677f\u60f3\u8981\u7684\u662f\u7ed3\u679c\uff0c\u4f60\u6ca1\u6709\u8fbe\u5230 Boss \u7684\u9884\u671f\uff0c\u96be\u9053\u8fd8\u8981\u4ed6\u53cd\u8fc7\u6765\u8be2\u95ee\u4f60\u4e8b\u60c5\u7684\u8be6\u7ec6\u7ecf\u8fc7\u5417\uff1f\u4f60\u662f\u4e0d\u662f\u5e94\u8be5\u7ed9\u51fa\u4e00\u4efd\u62a5\u544a\uff08\u54ea\u6015\u662f\u53e3\u5934\u5f62\u5f0f\uff09\uff0c\u7528\u4ee5\u8bf4\u660e\uff1a\n \u505a\u4e86\u54ea\u4e9b\u5c1d\u8bd5\uff1f \u9047\u5230\u600e\u6837\u7684\u56f0\u96be\uff1f \u662f\u5426\u8fd8\u6709\u5176\u4ed6\u65b9\u6848\uff1f \u2026\u2026  \u5f53\u6709\u4e86\u8fd9\u6837\u8be6\u7ec6\u7684\u62a5\u544a\uff0c\u6216\u8bb8\u8001\u677f\u3001\u751a\u81f3\u56e2\u961f\u4e2d\u7684\u540c\u4e8b\uff0c\u5c31\u53ef\u4ee5\u901a\u8fc7\u4f60\u6ca1\u6709\u7684\u8d44\u6e90\u3001\u4eba\u8109\u7b49\u65b9\u65b9\u9762\u9762\uff0c\u89e3\u51b3\u6389\u4f60\u5c1d\u8bd5\u8fc7\u3001\u4f46\u884c\u4e0d\u901a\u7684\u65b9\u6848\u3002\n\u82e5\u662f\u4f9d\u65e7\u89e3\u51b3\u4e0d\u6389\uff0c\u90a3\u4f60\u4e5f\u5e94\u8be5\u63d0\u51fa\u201c\u7f13\u89e3\u201d\u65b9\u6848\u3002\u8fd9\u65f6\u5019\uff0c\u5c31\u9700\u8981\u4f60\u660e\u786e\u8001\u677f\u7ed9\u4f60\u5b89\u6392\u7684\u5de5\u4f5c\uff0c\u80cc\u540e\u60f3\u8981\u8fbe\u5230\u7684\u76ee\u7684\u662f\u600e\u6837\u7684\u3001\u4ed6\u7684\u201c\u521a\u9700\u201d\u662f\u4ec0\u4e48\u3002\n\u6240\u8c13\u6761\u6761\u5927\u8def\u901a\u7f57\u9a6c\uff0c\u76ee\u6807\u662f\u6b7b\u7684\uff0c\u4eba\u662f\u6d3b\u7684\uff1b\u4ece\u201c\u521a\u9700\u201d\u7684\u89d2\u5ea6\u51fa\u53d1\uff0c\u601d\u8003\u662f\u5426\u6709\u5176\u4ed6\u201c\u901a\u5411\u7f57\u9a6c\u201d\u7684\u8def\u3002\n\u901a\u5e38\uff0c\u6b64\u65f6\u7684\u89e3\u51b3\u65b9\u6848\u76ee\u6807\u5df2\u7ecf\u4e0d\u518d\u662f\u5706\u6ee1\u8fbe\u5230\u9884\u671f\uff0c\u800c\u4e0d\u5f97\u4e0d\u6709\u4e00\u5b9a\u7684\u820d\u5f03\uff0c\u53ea\u8981\u820d\u5f03\u7684\u4e0d\u662f\u5f71\u54cd\u5927\u5c40\u3001\u521a\u9700\u3001\u6838\u5fc3\u5229\u76ca\u7684\u4e1c\u897f\uff0c\u90fd\u53ef\u4ee5\u5217\u5728\u4f60\u7684\u62a5\u544a\u91cc\uff1a\n \u662f\u5426\u6709\u201c\u5706\u6ed1\u201d\u7684\u89e3\u51b3\u65b9\u6848\uff1f \u80fd\u8fbe\u5230\u600e\u6837\u7684\u6548\u679c\uff1f \u6240\u5e26\u6765\u7684\u6210\u672c\u591a\u5c11\uff1f\u4ee3\u4ef7\u5982\u4f55\uff1f \u2026\u2026  \u81f3\u4e8e\u5982\u4f55\u9009\u62e9\uff0c\u51b3\u7b56\u6743\u5df2\u7ecf\u5168\u90e8\u5728\u8001\u677f\u624b\u91cc\uff0c\u4ed6\u53ea\u8981\u505a\u4e2a\u7b80\u5355\u7684\u9009\u62e9\u9898\u5373\u53ef\uff0c\u800c\u4e0d\u662f\u95ee\u7b54\u9898\u3002\n\u6b64\u65f6\uff0c\u4f18\u52a3\u4ee3\u4ef7\u5df2\u7ecf\u5168\u90e8\u5728 Boss \u5fc3\u4e2d\u6709\u6570\uff0c\u63a5\u4e0b\u6765\u4f60\u6240\u505a\u7684\uff0c\u5c31\u662f\u6267\u884c\u8001\u677f\u9009\u62e9\u7684\u65b9\u6848\u5c31\u597d\u3002\n\u8fd9\u624d\u662f\u771f\u6b63\u7684\uff1a\u201c\u6211\u5c3d\u529b\u4e86\u201d\u3002\n\u6709\u5174\u8da3\u53ef\u4ee5\u770b\u770b\u300a\u8bf4\u8bdd\u7684\u827a\u672f\u300b\u3002\n0x03 \u62d3\u5c55 \u7531\u6b64\uff0c\u53c8\u56de\u5230\u4e86\u6211\u5e73\u65f6\u5e38\u5e38\u6302\u5728\u5634\u8fb9\u7684\u7406\u8bba\uff1a\n \u7acb\u8db3\u7a0b\u5e8f\u5458\uff0c\u773c\u754c\u9ad8\u4e8e\u7a0b\u5e8f\u5458\u3002\n **\u7acb\u8db3\u7a0b\u5e8f\u5458**\u6307\u7684\u662f\u7740\u624b\u5f53\u4e0b\uff0c\u628a\u81ea\u5df1\u5e94\u8be5\u505a\u7684\u4e8b\u505a\u597d\u3001\u6240\u8981\u627f\u62c5\u7684\u8d23\u4efb\u627f\u62c5\u8d77\u6765\uff0c\u4fdd\u8bc1\u81ea\u5df1\u5199\u7684\u4ee3\u7801\u4e0d\u51fa\u95ee\u9898\u3002\n**\u9ad8\u4e8e\u7a0b\u5e8f\u5458**\u6307\u7684\u662f\u653e\u773c\u5168\u5c40\uff0c\u5728\u505a\u7a0b\u5e8f\u5458\u7684\u540c\u65f6\u591a\u601d\u8003\uff1a\n \u4ece\u540c\u4e8b\u89d2\u5ea6\u60f3\uff0c\u81ea\u5df1\u7684\u4ee3\u7801\u548c\u522b\u4eba\u5bf9\u63a5\u662f\u5426\u65b9\u4fbf\uff1f\u6709\u6ca1\u6709\u53ef\u80fd\u4ea7\u751f\u7684\u8bef\u4f1a\uff1f \u4ece\u9ad8\u7ea7\u7a0b\u5e8f\u5458\u89d2\u5ea6\u60f3\uff0c\u67d0\u6761\u4ee3\u7801\u662f\u4e0d\u662f\u53ef\u4ee5\u518d\u4f18\u5316\u5f97\u66f4\u5b8c\u5584\u3001\u66f4\u4f18\u96c5\uff1f \u4ece\u67b6\u6784\u5e08\u89d2\u5ea6\u60f3\uff0c\u67d0\u5757\u4ee3\u7801\u662f\u4e0d\u662f\u53ef\u4ee5\u8fdb\u884c\u5feb\u901f\u91cd\u6784\u4f7f\u5176\u5177\u6709\u66f4\u9ad8\u7684\u6269\u5c55\u6027\u3001\u5065\u58ee\u6027\u3001\u53ef\u7ef4\u62a4\u6027\u7b49\u7b49\uff1f \u4ece\u8001\u677f\u89d2\u5ea6\u60f3\uff0c\u8fd9\u5957\u7cfb\u7edf\u6709\u6ca1\u6709\u6f5c\u5728\u98ce\u9669\u3001\u989d\u5916\u6210\u672c\u6216\u662f\u4e0d\u786e\u5b9a\u56e0\u7d20\uff1f \u4ece\u5ba2\u6237\u89d2\u5ea6\u60f3\uff0c\u6211\u4eec\u7684\u4ea7\u54c1\u662f\u5426\u597d\u7528\uff1f\u7ec6\u8282\u4f53\u9a8c\u662f\u5426\u5b8c\u7f8e\uff1f\u6709\u6ca1\u6709\u89e3\u51b3\u76ee\u524d\u6838\u5fc3\u95ee\u9898\uff1f  \u8fd9\u6837\uff0c\u624d\u6709\u673a\u4f1a\u4ece\u7a0b\u5e8f\u5458\u4e2d\u8131\u9896\u800c\u51fa\uff0c\u6210\u4e3a\u53d7\u5230\u8001\u677f\u3001\u751a\u81f3\u5ba2\u6237\u9752\u7750\u7684\u4f7c\u4f7c\u8005\u3002\n0x04 \u601d\u8003 \u4e3a\u4ec0\u4e48\u4f1a\u51fa\u73b0\u8fd9\u6837\u7684\u95ee\u9898\uff1f\n\u662f\u56fd\u5185\u6b7b\u677f\u7684\u5f00\u53d1\u6d41\u7a0b\u9020\u5c31\u4e86\u8fd9\u6837\u4e00\u6279\u4e0d\u4f1a\u52a8\u8111\u7b4b\u7684\u7a0b\u5e8f\u5458\uff1f\n\u8fd8\u662f\u4ece\u6700\u521d\u7684\u6a21\u677f\u5f0f\u6559\u80b2\u5c31\u56fa\u5316\u4e86\u5b69\u5b50\u539f\u672c\u591a\u5f69\u591a\u6837\u7684\u601d\u7ef4\u3002\n \u6587\u91c7\u6709\u9650\uff0c\u6b22\u8fce\u6279\u8bc4\u6307\u6b63\u3002\n ","permalink":"https:\/\/wi1dcard.dev\/posts\/the-world-isnt-only-true-or-false\/","summary":"0x00 \u524d\u8a00 \u66fe\u7ecf\u548c\u4e00\u4f4d\u4e0d\u505a\u6280\u672f\u3001\u4f46\u4e0e\u6280\u672f\u4eba\u5458\u6709\u5408\u4f5c\u7684\u670b\u53cb\u804a\u5929\uff0c\u4ed6\u4f5c\u4e3a\u4e00\u540d\u5c0f\u9886\u5bfc\uff0c\u5e38\u548c\u5916\u5305\u7a0b\u5e8f\u5458\u6253\u4ea4\u9053\u3002\u6211\u95ee\u4ed6\uff1a\u4f60\u89c9\u5f97\u505a\u7a0b\u5e8f\u5458\u6700\u5fcc\u8bb3\u4ec0\u4e48\uff1f\u4ed6\u7684\u56de\u7b54\u662f\uff1a\n \u4e0d\u8981\u8ba9\u8111\u888b\u91cc\u53ea\u5269\u4e0b\u662f\u4e0e\u975e\u3001\u96f6\u548c\u4e00\u3002\n\u4f5c\u8005\uff1a\u5b59\u4f1f\u5586\uff0f2017-10-15\n 0x01 \u95ee\u9898 \u90a3\u65f6\u5019\u4e0d\u61c2\u8fd9\u53e5\u8bdd\u7684\u6211\u4e00\u5fc3\u53ea\u987e\u94bb\u7814\u6280\u672f\uff0c\u4e8e\u662f\u8ffd\u95ee\uff1a\u4f55\u51fa\u6b64\u8a00\uff1f\n \u597d\u591a\u7a0b\u5e8f\u5458\u505a\u4e45\u4e86\u6280\u672f\uff0c\u4e60\u60ef\u4e86\u9762\u5bf9\u4ee3\u7801\uff0c\u6709\u65f6\u5019\u53ef\u4ee5\u660e\u663e\u611f\u89c9\u5230\u4ed6\uff08\u4eec\uff09\u7f3a\u4e4f\u4e86\u4e00\u4e9b\u57fa\u672c\u7684\u611f\u6027\u601d\u7ef4\u3002\u6bd4\u65b9\u8bf4\uff0c\u5ba2\u6237\u63d0\u51fa\u7684\u9700\u6c42\uff0c\u7ed9\u51fa\u7684\u7b54\u590d\u603b\u662f\uff1a\u6211\u53ea\u60f3\u8981\u4f60\u660e\u786e\u7684\u903b\u8f91\uff0c\u4e0d\u8981\u8ddf\u6211\u8bb2\u592a\u591a\uff1b\u53c8\u6216\u662f\u5bf9\u4e8e\u4ea7\u54c1\u7ecf\u7406\u53e3\u4e2d\u7684\u67d0\u4e2a\u6548\u679c\uff0c\u53ea\u6709\u4e24\u6761\u8def\uff1a\u53ef\u4ee5\u5b9e\u73b0\uff0f\u5b9e\u73b0\u4e0d\u4e86\uff1b\u8fd9\u8ba9\u6211\u96be\u4ee5\u63a5\u53d7\u3002\n \u662f\u554a\uff01\u4e16\u754c\u4e0a\u7684\u4e8b\u60c5\u600e\u4e48\u4f1a\u6709\u660e\u786e\u7684\u5206\u754c\u7ebf\uff0c\u4eba\u7684\u601d\u7ef4\u662f\u66f2\u7ebf\u7684\uff0c\u6700\u6015\u601d\u7ef4\u56fa\u5316\u3001\u4e00\u6839\u7b4b\u3002\n0x02 \u5206\u6790 \u56de\u5230\u670b\u53cb\u63d0\u51fa\u7684\u4e24\u4e2a\u4f8b\u5b50\uff1a\n\u5ba2\u6237\u6784\u60f3\u7684\u9700\u6c42  \u9996\u5148\u8981\u660e\u767d\uff0c\u5ba2\u6237\u662f\u666e\u901a\u4eba\uff0c\u4e0d\u61c2\u4ee3\u7801\u3002 \u5176\u6b21\uff0c\u5ba2\u6237\u63d0\u51fa\u7684\u9700\u6c42\u6c38\u8fdc\u53ea\u662f\u8111\u888b\u4e2d\u7684\u6784\u60f3\uff0c\u5982\u4f55\u628a\u6784\u60f3\u53d8\u6210\u73b0\u5b9e\u662f\u4f60\u7684\u4e8b\u60c5\uff0c\u800c\u4e0d\u662f\u5ba2\u6237\u9700\u8981\u601d\u8003\u7684\u4e1c\u897f\u3002 \u4f5c\u4e3a\u4e59\u65b9\uff0c\u6211\u4eec\u5e94\u8be5\u4e3b\u52a8\u534f\u52a9\u4e0d\u61c2\u4ee3\u7801\u7684\u201c\u5c0f\u767d\u201d\u5ba2\u6237\u786e\u5b9a\u4ed6\u60f3\u8981\u7684\u662f\u4ec0\u4e48\uff0c\u5ba2\u6237\u601d\u7ef4\u6240\u53ca\u53ea\u80fd\u505c\u7559\u5728\u4e0e\u6280\u672f\u65e0\u5173\u7684\u5c42\u6b21\u4e0a\uff0c\u90a3\u4e48\u63a5\u4e0b\u6765\u5c31\u9700\u8981\u4f60\u5e26\u9886\u5ba2\u6237\u53bb\u5206\u6790\uff0c\u7406\u6e05\u4ed6\u7684\u903b\u8f91\uff0c\u540c\u65f6\u4e5f\u8981\u601d\u8003\u5728\u6280\u672f\u5c42\u9762\u4e0a\u5982\u4f55\u5b9e\u73b0\u3002\u5ba2\u6237\u4e0d\u4e86\u89e3\u5728\u8f6f\u4ef6\u884c\u4e1a\u6b64\u7c7b\u201c\u6784\u60f3\u201d\u662f\u5982\u4f55\u5b9e\u73b0\uff0c\u800c\u6211\u4eec\u4e0d\u61c2\u5ba2\u6237\u884c\u4e1a\u5185\u7684\u89c4\u5219\uff0c\u5728\u4f60\u4e3b\u52a8\u5e26\u9886\u5ba2\u6237\u5206\u6790\u9700\u6c42\u3001\u5bf9\u9700\u6c42\u201c\u5177\u4f53\u5316\u201d\u7684\u65f6\u5019\uff0c\u5ba2\u6237\u53ef\u4ee5\u8ddf\u5f97\u4e0a\u4f60\u7684\u601d\u7ef4\uff0c\u53ca\u65f6\u4fee\u6b63\u4f60\u6240\u8bf4\u7684\u662f\u5426\u6709\u6240\u504f\u5dee\uff0c\u751a\u81f3\u6709\u53ef\u80fd\u6253\u5f00\u4e86\u601d\u8def\uff0c\u4e3b\u52a8\u8bf4\u51fa\u67d0\u4e00\u6a21\u5757\u7684\u7ec6\u8282\uff1b\u800c\u8fd9\u65f6\u5019\uff0c\u75af\u72c2\u7684\u8bb0\u7b14\u8bb0\u5c31\u597d\u4e86\u3002  \u5173\u4e8e\u4e0a\u9762\u8fd9\u6761\u7406\u8bba\uff0c\u6709\u4e2a\u5f88\u5178\u578b\u53c8\u7c7b\u4f3c\u7684\u4f8b\u5b50\uff1a","title":"\u4e0d\u8981\u8ba9\u8111\u888b\u91cc\u53ea\u5269 0 \u548c 1 \u2014\u2014 \u907f\u514d\u601d\u7ef4\u56fa\u5316"},{"content":"sudo killall -HUP mDNSResponder; sudo killall mDNSResponderHelper; sudo dscacheutil -flushcache ","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-flush-dns-cache\/","summary":"sudo killall -HUP mDNSResponder; sudo killall mDNSResponderHelper; sudo dscacheutil -flushcache ","title":"macOS \u6e05\u9664 DNS \u7f13\u5b58\u547d\u4ee4"},{"content":" \u672c\u6587\u603b\u7ed3\u5e38\u7528\u91cd\u5199\u89c4\u5219\u3002\n Laravel 5 location\u00a0\/\u00a0{ try_files\u00a0$uri\u00a0$uri\/\u00a0\/index.php?$query_string; } Vue.js https:\/\/router.vuejs.org\/zh-cn\/essentials\/history-mode.html\nlocation\u00a0\/\u00a0{ try_files\u00a0$uri\u00a0$uri\/\u00a0\/index.html; } Yii 2 location \/ { try_files $uri $uri\/ \/index.php?$args; } apache .htaccess\nOptions +FollowSymLinks RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] ","permalink":"https:\/\/wi1dcard.dev\/posts\/laravel-vue-rewrite-rules\/","summary":"\u672c\u6587\u603b\u7ed3\u5e38\u7528\u91cd\u5199\u89c4\u5219\u3002\n Laravel 5 location\u00a0\/\u00a0{ try_files\u00a0$uri\u00a0$uri\/\u00a0\/index.php?$query_string; } Vue.js https:\/\/router.vuejs.org\/zh-cn\/essentials\/history-mode.html\nlocation\u00a0\/\u00a0{ try_files\u00a0$uri\u00a0$uri\/\u00a0\/index.","title":"Laravel5 \u548c Vue.js \u4f18\u96c5\u7684 Nginx \u91cd\u5199\u89c4\u5219"},{"content":"  \u6253\u5f00 terminal\n  \u6267\u884c\u5982\u4e0b\u547d\u4ee4\uff1a\n  diskutil\u00a0list \u53ef\u67e5\u770b\u5168\u90e8\u5206\u533a\u7684\u540d\u5b57\uff0cMAC \u7cfb\u7edf\u9ed8\u8ba4\u6302\u8f7d\u5168\u90e8\u5206\u533a\u5230 \/Volumes \u76ee\u5f55\uff0c\n\u6267\u884c\u5982\u4e0b\u547d\u4ee4\uff1a  sudo\u00a0vim\u00a0\/etc\/fstab \u7f16\u8f91 fstab \u6587\u4ef6\uff0c\u6dfb\u52a0\u5982\u4e0b\u4e00\u884c\u5e76\u4fdd\u5b58\uff1a\nLABEL=\u300c\u5206\u533a\u540d\u300d\u00a0none\u00a0ntfs\u00a0rw,auto,nobrowse,nosuid \u5177\u4f53\u53c2\u6570\u503c\u542b\u4e49\u53ef\u4ee5\u81ea\u884c\u8c37\u6b4c\u3002\n\u7531\u4e8e\u8bbe\u7f6e\u597d\u4e4b\u540e\uff0c\u78c1\u76d8\u4e0d\u4f1a\u5728 Finder \u5185\u663e\u793a\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5efa\u4e2a\u8f6f\u94fe\u63a5\u5230\u684c\u9762\u65b9\u4fbf\u8bbf\u95ee\uff1a  sudo\u00a0ln\u00a0-s\u00a0\/Volumes\u00a0~\/Desktop\/Volumes \u6ce8\uff1aMAC \u7cfb\u7edf\u9ed8\u8ba4\u6302\u8f7d\u5168\u90e8\u5206\u533a\u5230 \/Volumes \u76ee\u5f55\uff0c\u6240\u4ee5\u4f60\u4e5f\u53ef\u4ee5\u5355\u72ec\u94fe\u63a5\u67d0\u4e2a Volume\u3002\nReboot!  ","permalink":"https:\/\/wi1dcard.dev\/posts\/macos-write-ntfs-driver\/","summary":"\u6253\u5f00 terminal\n  \u6267\u884c\u5982\u4e0b\u547d\u4ee4\uff1a\n  diskutil\u00a0list \u53ef\u67e5\u770b\u5168\u90e8\u5206\u533a\u7684\u540d\u5b57\uff0cMAC \u7cfb\u7edf\u9ed8\u8ba4\u6302\u8f7d\u5168\u90e8\u5206\u533a\u5230 \/Volumes \u76ee\u5f55\uff0c\n\u6267\u884c\u5982\u4e0b\u547d\u4ee4\uff1a  sudo\u00a0vim\u00a0\/etc\/fstab \u7f16\u8f91 fstab \u6587\u4ef6\uff0c\u6dfb\u52a0\u5982\u4e0b\u4e00\u884c\u5e76\u4fdd\u5b58\uff1a","title":"macOS \u6253\u5f00\u81ea\u5e26 NTFS \u5199\u6587\u4ef6\u529f\u80fd"},{"content":"9.20 updated:\n\u4eca\u5929\u68c0\u67e5\u591a\u5bb6\u516c\u53f8\u7684\u7ba1\u7406\u7aef\u9875\u9762\u65f6\u53d1\u73b0\uff0c\u5c45\u7136\u5176\u4ed6\u516c\u53f8\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u7684\u6d4b\u8bd5\u6570\u636e\uff0c\u9042\u68c0\u67e5\u6570\u636e\u5e93\uff0c\u5e76\u4e0d\u5b58\u5728\u6d4b\u8bd5\u6570\u636e\uff0c\u53c8\u53bb\u7ffb\u914d\u7f6e env \u6587\u4ef6\uff0c\u6570\u636e\u5e93\u914d\u7f6e\u6b63\u5e38\uff0c\u53c8\u6392\u9664 rsync \u540c\u6b65\u4e86 config \u7f13\u5b58\u7684\u53ef\u80fd\u4e4b\u540e\uff0c\u6700\u7ec8\u53d1\u73b0\u662f nginx \u914d\u7f6e\u5f15\u8d77\u7684\u53cd\u5411\u4ee3\u7406\u5168\u90e8\u8fdb\u4e86 demo \u670d\u52a1\u5668\u3002\u3002\u3002\n\u4e0d\u8fc7\u8fd9\u4e5f\u5f15\u8d77\u4e86\u6211\u7684\u91cd\u89c6\uff1a\u7531\u4e8e laravel cache \u9a71\u52a8\u4e3a file\uff0c\u800c rsync \u540c\u6b65\u5217\u8868\u5e76\u6ca1\u6709\u6392\u9664bootstrap\/cache\/config.php\uff0c\u8fd9\u6837\u4f1a\u5bfc\u81f4\u6267\u884cphp artisan config:cache\u7f13\u5b58\u547d\u4ee4\u540e\uff0c\u5168\u90e8\u516c\u53f8\u90fd\u8fde\u63a5\u540c\u4e00\u4e2a\u6570\u636e\u5e93\uff01\n\u4e8e\u662f\u5f00\u59cb\u89e3\u51b3\u95ee\u9898\uff1a\nstep1.\nexclude.list \u5355\u72ec\u5199\u4e3a\u4e00\u4e2a\u6587\u4ef6\uff0c\u4e00\u884c\u4e00\u6761\u9700\u8981\u6392\u9664\u7684\u76f8\u5bf9\u8def\u5f84\uff1b\u5176\u4e2d\uff0c\u6dfb\u52a0\uff1abootstrap\/cache\/config.php\uff0c\u6392\u9664\u6b64\u6587\u4ef6\u3002\nstep2.\n\u628a\u539f exclude \u53c2\u6570\u6539\u4e3a\uff1aexclude-from=&lt;path&gt;\/exclude.list\uff0c\u8fd9\u6837\u540c\u6b65\u7684\u65f6\u5019\u5c31\u4f1a\u6392\u9664\u6389 list \u91cc\u7684\u5168\u90e8\u8def\u5f84\u4e86\u3002\ndone!\n\u53e6\u5916\uff0crsync \u53ef\u4ee5\u5b9e\u73b0\u540c\u6b65\u672c\u673a\u6587\u4ef6\uff0c\u5982\u4e0b\uff1a\nrsync\u00a0-avzP\u00a0--delete\u00a0sgbd\/\u00a0xlba\/\u00a0--exclude-from='\/home\/wwwroot\/env\/ext\/exclude.list' \u76f4\u63a5\u5199\u4e24\u4e2a\u76f8\u5bf9\u8def\u5f84\uff08\u6e90\u3001\u76ee\u6807\uff09\u5c31\u53ef\u4ee5\u4e86\u3002\n \u7531\u4e8e\u9879\u76ee\u9700\u8981\uff0c\u6545\u914d\u7f6e rsync-server \u548c rsync-client \u540c\u6b65 laravel \u6e90\u7801\uff0c\u5176\u4e2d rsync-server \u4f7f\u7528 amh \u9762\u677f\u5b89\u88c5\u597d\uff0cweb \u914d\u7f6e\u5b8c\u6210\u5373\u53ef\uff0c\u4f46 rsync-client \u9700\u8981\u5355\u72ec\u8fdb\u884c\u914d\u7f6e\u3002\n\u9700\u6c42\u5982\u4e0b\uff1a\n1\uff0c.env \u6587\u4ef6\u4e0d\u5f97\u540c\u6b65\uff08\u6bcf\u53f0 client \u7684.env \u914d\u7f6e\u6587\u4ef6\u4e0d\u540c\uff09\n2\uff0cstorage \u6587\u4ef6\u5939\u53ea\u540c\u6b65\u76ee\u5f55\u7ed3\u6784\n3\uff0c\u81ea\u52a8\u5b9a\u65f6\u540c\u6b65\n step.0\n\u5b89\u88c5 rsync-client\nstep.1\n\u7531\u4e8e\u6211\u4eec\u540c\u6b65\u670d\u52a1\u5668\u4f7f\u7528 rsync-server \u800c\u975e ssh\uff0c\u6240\u4ee5\u9700\u8981\u7528\u5230.pass \u6587\u4ef6\u914d\u7f6e\u79d8\u94a5\ncd\u00a0\/home\/usrdata\/rsync-client-3.1\/etc\/ echo\u00a0{YOUR_PASSWORD}\u00a0&gt;\u00a0test.pass \u8fd9\u6837\u5c31\u628a\u79d8\u94a5\u8f93\u51fa\u5230 test.pass \u6587\u4ef6\u4e86\nstep.2\n\u7f16\u5199 sh \u811a\u672c\uff0c\u5b9e\u73b0\u5982\u4e0a\u9700\u6c42\nrsync\u00a0-avzP\u00a0--delete\u00a0--password-file=\/home\/usrdata\/rsync-client-3.1\/etc\/test.pass\u00a0rsync:\/\/root@172.17.0.4\/root\u00a0\/home\/wwwroot\/demo\/domain\/demo\/web\/\u00a0--include='*\/'\u00a0--exclude='*' rsync\u00a0-avzP\u00a0--delete\u00a0--password-file=\/home\/usrdata\/rsync-client-3.1\/etc\/test.pass\u00a0rsync:\/\/root@172.17.0.4\/root\u00a0\/home\/wwwroot\/demo\/domain\/demo\/web\/\u00a0--exclude=.env\u00a0--exclude=storage \u7b2c\u4e00\u884c&ndash;include='\/&lsquo;\u5373\u4e3a\u5305\u542b\u5168\u90e8\u76ee\u5f55\uff0c&ndash;exclude='&lsquo;\u5373\u4e3a\u6392\u9664\u5168\u90e8\u6587\u4ef6\uff0c\u8fd9\u6837\u5168\u90e8\u7684\u76ee\u5f55\u7ed3\u6784\u5c31\u540c\u6b65\u4e0b\u6765\u4e86\u3002\n\u7b2c\u4e8c\u884c\u4e24\u4e2a exclude\uff0c\u5206\u522b\u662f\u6392\u9664 storage \u76ee\u5f55\u548c.env \u6587\u4ef6\uff0c\u56e0\u4e3a\u524d\u9762\u6211\u4eec\u5df2\u7ecf\u540c\u6b65\u5168\u90e8\u76ee\u5f55\u7ed3\u6784\uff0c\u6240\u4ee5\u76f4\u63a5\u6392\u9664\u6389 storage \u540c\u6b65\u5373\u53ef\u3002\n\u6700\u7ec8\uff1a\u628a\u8fd9\u4e24\u884c\u5199\u5230\u67d0\u4e2a sh \u6587\u4ef6(e.g. test.sh)\u5373\u53ef\uff0c\u5373\u53ef\u5b9e\u73b0 1\u30012 \u4e24\u4e2a\u9700\u6c42\u3002\nstep.3\n\u81ea\u52a8\u5b9a\u65f6\uff0c\u5f53\u7136\u662f\u7528 crontab \u5566\u3002\ncrontab\u00a0-e\u00a0##\u00a0\u7f16\u8f91\u5b9a\u65f6\u4efb\u52a1 *\/5\u00a0*\u00a0*\u00a0*\u00a0*\u00a0bash\u00a0\/home\/usrdata\/rsync-client-3.1\/etc\/test.sh\u00a0&gt;\u00a0\/tmp\/rsync.log\u00a0##\u00a0\u8ffd\u52a0\u6b64\u884c,\u6bcf\u4e94\u5206\u949f\u540c\u6b65\u4e00\u6b21 done!\nreference:\u00a0https:\/\/blog.csdn.net\/david_xtd\/article\/details\/10149617\n","permalink":"https:\/\/wi1dcard.dev\/posts\/depoly-code-to-multiple-servers-with-rsync\/","summary":"9.20 updated:\n\u4eca\u5929\u68c0\u67e5\u591a\u5bb6\u516c\u53f8\u7684\u7ba1\u7406\u7aef\u9875\u9762\u65f6\u53d1\u73b0\uff0c\u5c45\u7136\u5176\u4ed6\u516c\u53f8\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u7684\u6d4b\u8bd5\u6570\u636e\uff0c\u9042\u68c0\u67e5\u6570\u636e\u5e93\uff0c\u5e76\u4e0d\u5b58\u5728\u6d4b\u8bd5\u6570\u636e\uff0c\u53c8\u53bb\u7ffb\u914d\u7f6e env \u6587\u4ef6\uff0c\u6570\u636e\u5e93\u914d\u7f6e\u6b63\u5e38\uff0c\u53c8\u6392\u9664 rsync \u540c\u6b65\u4e86 config \u7f13\u5b58\u7684\u53ef\u80fd\u4e4b\u540e\uff0c\u6700\u7ec8\u53d1\u73b0\u662f nginx \u914d\u7f6e\u5f15\u8d77\u7684\u53cd\u5411\u4ee3\u7406\u5168\u90e8\u8fdb\u4e86 demo \u670d\u52a1\u5668\u3002\u3002\u3002\n\u4e0d\u8fc7\u8fd9\u4e5f\u5f15\u8d77\u4e86\u6211\u7684\u91cd\u89c6\uff1a\u7531\u4e8e laravel cache \u9a71\u52a8\u4e3a file\uff0c\u800c rsync \u540c\u6b65\u5217\u8868\u5e76\u6ca1\u6709\u6392\u9664bootstrap\/cache\/config.php\uff0c\u8fd9\u6837\u4f1a\u5bfc\u81f4\u6267\u884cphp artisan config:cache\u7f13\u5b58\u547d\u4ee4\u540e\uff0c\u5168\u90e8\u516c\u53f8\u90fd\u8fde\u63a5\u540c\u4e00\u4e2a\u6570\u636e\u5e93\uff01","title":"\u670d\u52a1\u5668\u6e90\u7801\u540c\u6b65\uff1arsync \u914d\u7f6e\u8fc7\u7a0b\u5c0f\u8bb0"},{"content":"\u4eca\u5929\u6c88\u540c\u5b66\u6765\u95ee c# \u8bfb ic \u5361\u7684\u95ee\u9898\uff0c\u6211\u7b2c\u4e00\u53cd\u5e94\u662f\u60f3\u5230\u4e86 windows \u63d0\u4f9b\u7684\u667a\u80fd\u5361\u9a71\u52a8 API\uff0c\u4e4b\u524d\u7528 c++\u5b9e\u73b0\u8fc7\u4e00\u5957\u3002\nreference\uff1ahttps:\/\/docs.microsoft.com\/zh-cn\/previous-versions\/windows\/desktop\/secsmart\/smart-card-api-portal\n\u53ef\u53ea\u6709\u82f1\u8bed\uff0c\u5bf9\u4e8e\u6ca1\u6709\u9605\u8bfb\u8fc7\u539f\u7248 MSDN \u7684\u5b9e\u4e60\u751f\u6765\u8bf4\u6709\u4e00\u5b9a\u96be\u5ea6\uff0c\u5373\u4fbf\u6709\u590d\u6742\u7684 c++\u6e90\u7801\u53c2\u7167\uff0c\u4f30\u8ba1\u4e5f\u8981\u7814\u7a76\u4e2a\u51e0\u5929\u3002\nso\uff0c\u7528 c# \u5199 windows\uff0c\u8981\u7684\u5c31\u662f\u5b83\u7684\u8f6e\u5b50\u591a\u3002\u9047\u5230\u8fd9\u79cd\u60c5\u51b5\uff0c\u679c\u65ad\u7f51\u4e0a\u641c\u4e00\u4e0b\u5148\uff0c\u4f46\u7ed3\u679c\u4e0d\u5c3d\u4eba\u610f\uff0c\u5927\u591a\u90fd\u662f\u4e13\u95e8\u7528\u4e8e\u67d0\u4e2a\u578b\u53f7\u8bfb\u5361\u5668\u7684\u5382\u5bb6\u63d0\u4f9b\u7684 SDK\u3002\n\u4e8e\u662f\u679c\u65ad\u53bb\u5fae\u8f6f\u5b98\u65b9\u7684\u5305\u7ba1\u7406\u5668 nuget \u91cc\u627e\uff0c\uff08keyword\uff1asmart card\uff09\u2026\u2026\n\uff08\u53f3\u952e\u5355\u51fb\u5f15\u7528\uff0c\u9009\u62e9\u7ba1\u7406 nuget \u7a0b\u5e8f\u5305\uff09\n\uff08\u5355\u51fb\u6d4f\u89c8\uff0c\u7136\u540e\u641c\u7d22\uff09\n\u770b\u8fd9\u4e2a\u540d\u5b57\u6bd4\u8f83\u50cf\u6211\u4eec\u9700\u8981\u7684\u4e1c\u897f\uff0c\u4e8e\u662f\u70b9\u51fb\u53f3\u8fb9\u7684\u4e0b\u8f7d\u6309\u94ae\u4e0b\u8f7d\u5373\u53ef\u81ea\u52a8\u4e0b\u8f7d\u5b89\u88c5\uff0c\u975e\u5e38\u65b9\u4fbf\u3002\u5982\u9047\u5230\u4e0b\u8f7d\u7f13\u6162\u7684\u60c5\u51b5\u8bf7\u81ea\u884c\u79d1\u5b66\u4e0a\u7f51\u3002\n\u5b89\u88c5\u5b8c\u6210\u4e4b\u540e\uff0c\u76f4\u63a5\u4e0d\u627e\u6587\u6863\u4e86\uff0c\u8fd9\u79cd\u5c0f\u4e1c\u897f\u76f4\u63a5\u770b\u7c7b\u58f0\u660e\uff1a\n\uff08\u5de6\u4fa7\u5f15\u7528-&gt;\u547d\u540d\u7a7a\u95f4\u540d\uff0c\u53f3\u4fa7\u65b0 Tab \u91cc\u53cc\u51fb\u5c55\u5f00\uff0c\u5c31\u80fd\u770b\u5230\u547d\u540d\u7a7a\u95f4\u548c\u5305\u542b\u7684\u7c7b\u578b\uff09\n\u53ef\u4ee5\u770b\u5230\uff0c\u8fd9\u4e2a\u5e93\u975e\u5e38\u7b80\u6d01\uff0c\u53ea\u6709\u4e24\u4e2a\u7c7b\uff0c\u6211\u559c\u6b22 2333~\n\u8fdb\u53bb\u770b\u4e0b\u8fd9\u4e24\u4e2a\u7c7b\u7684\u65b9\u6cd5\uff0c\u57fa\u672c\u4e0a\u80fd\u591f\u987e\u540d\u601d\u4e49\uff0c\u8bdd\u4e0d\u591a\u8bf4\uff0c\u76f4\u63a5\u4e0a\u624b\u5199\u4ee3\u7801\u5c1d\u8bd5\uff1a\nusing\u00a0TOC.SmartCardReader; using\u00a0System.Diagnostics; \/\/\u667a\u80fd\u5361\u4e0a\u4e0b\u6587\u53d8\u91cf  HDMICardContext\u00a0CardContext; private\u00a0void\u00a0Form1_Load(object\u00a0sender,\u00a0EventArgs\u00a0e) { \/\/new\u4e0a\u4e0b\u6587  this.CardContext\u00a0=\u00a0new\u00a0HDMICardContext(); \/\/\u521d\u59cb\u5316  var\u00a0res\u00a0=\u00a0CardContext.Initilize(); \/\/\u5224\u65ad\u521d\u59cb\u5316\u7ed3\u679c  if\u00a0(!res) { MessageBox.Show(&#34;fatal!&#34;); return; } \/\/\u6302\u8f7d\u4e8b\u4ef6\u5904\u7406\u51fd\u6570  CardContext.CardInserted\u00a0+=\u00a0new\u00a0EventHandler(CardInserted); } private\u00a0void\u00a0CardInserted(object\u00a0sender,\u00a0EventArgs\u00a0args) { \/\/\u8fd9\u91cc\u6700\u5f00\u59cb\u6709\u70b9\u61f5\uff0c\u4e0d\u77e5\u9053\u600e\u4e48\u62ff\u5230Result\uff0c\u4e0b\u65ad\u70b9\u770b\u4e86\u4e00\u4e0bsender\u7684\u7c7b\u578b\u5c31\u662f\u6211\u4eec\u8981\u7684Result\uff0c\u4e8e\u662f\u76f4\u63a5as\u4e00\u4e0b\u7136\u540e\u8f93\u51fa\u5373\u53ef  var\u00a0res\u00a0=\u00a0sender\u00a0as\u00a0TOC.SmartCardReader.Models.SmartCardResult; Debug.WriteLine(string.Format(&#34;inserted,\u00a0card\u00a0uid:\u00a0{0}&#34;,\u00a0res.CardUID)); } \u5b8c\u6210\uff0c\u7a0b\u5e8f\u8fd0\u884c\u5373\u53ef\u770b\u5230\u8f93\u51fa\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/read-uids-of-ic-cards\/","summary":"\u4eca\u5929\u6c88\u540c\u5b66\u6765\u95ee c# \u8bfb ic \u5361\u7684\u95ee\u9898\uff0c\u6211\u7b2c\u4e00\u53cd\u5e94\u662f\u60f3\u5230\u4e86 windows \u63d0\u4f9b\u7684\u667a\u80fd\u5361\u9a71\u52a8 API\uff0c\u4e4b\u524d\u7528 c++\u5b9e\u73b0\u8fc7\u4e00\u5957\u3002\nreference\uff1ahttps:\/\/docs.microsoft.com\/zh-cn\/previous-versions\/windows\/desktop\/secsmart\/smart-card-api-portal\n\u53ef\u53ea\u6709\u82f1\u8bed\uff0c\u5bf9\u4e8e\u6ca1\u6709\u9605\u8bfb\u8fc7\u539f\u7248 MSDN \u7684\u5b9e\u4e60\u751f\u6765\u8bf4\u6709\u4e00\u5b9a\u96be\u5ea6\uff0c\u5373\u4fbf\u6709\u590d\u6742\u7684 c++\u6e90\u7801\u53c2\u7167\uff0c\u4f30\u8ba1\u4e5f\u8981\u7814\u7a76\u4e2a\u51e0\u5929\u3002\nso\uff0c\u7528 c# \u5199 windows\uff0c\u8981\u7684\u5c31\u662f\u5b83\u7684\u8f6e\u5b50\u591a\u3002\u9047\u5230\u8fd9\u79cd\u60c5\u51b5\uff0c\u679c\u65ad\u7f51\u4e0a\u641c\u4e00\u4e0b\u5148\uff0c\u4f46\u7ed3\u679c\u4e0d\u5c3d\u4eba\u610f\uff0c\u5927\u591a\u90fd\u662f\u4e13\u95e8\u7528\u4e8e\u67d0\u4e2a\u578b\u53f7\u8bfb\u5361\u5668\u7684\u5382\u5bb6\u63d0\u4f9b\u7684 SDK\u3002\n\u4e8e\u662f\u679c\u65ad\u53bb\u5fae\u8f6f\u5b98\u65b9\u7684\u5305\u7ba1\u7406\u5668 nuget \u91cc\u627e\uff0c\uff08keyword\uff1asmart card\uff09\u2026\u2026","title":"How to Read UIDs of IC Cards in C#"},{"content":"\u4eca\u5929\u9879\u76ee\u90e8\u7f72\u9047\u5230\u4e2a\u5751\uff0c\u4e4b\u524d\u5efa\u6570\u636e\u5e93\u7684\u65f6\u5019\uff0c\u628a\u6240\u6709\u7684 collation \u90fd\u5199\u6210\u4e86 utf8\uff0c\u5728\u6d4b\u8bd5\u670d\u52a1\u5668\u4e0a\u4e5f\u6ca1\u600e\u4e48\u6ce8\u610f\uff0c\u90e8\u7f72\u6b63\u5f0f\u670d\u52a1\u5668\u679c\u65ad\u7528 mb4\uff0c\u6545\u9700\u8981\u4fee\u6539\u4e0a\u767e\u4e2a\u5b57\u6bb5\u7684 collation\u3002\n\u6839\u636e\u4e00\u6b21\u53ef\u4ee5\uff0c\u4e24\u6b21\u80fd\u5fcd\uff0c\u4e09\u6b21\u7edd\u5bf9\u4e0d\u884c\u7684\u61d2\u4eba\u539f\u5219 orz\uff0c\u51b3\u5b9a\u5199\u4e2a\u811a\u672c\u5b9e\u73b0\u4e00\u952e\u4fee\u6539\uff0c\u5e9f\u8bdd\u4e0d\u591a\u8bf4\u5148\u53bb\u7f51\u4e0a\u627e\u4e86\u4e2a\u8f6e\u5b50\u3002\nreferer:\u00a0https:\/\/my.oschina.net\/xuqiang\/blog\/507629\n\u7ecf\u8fc7\u4e00\u756a\u4fee\u6539\u548c\u6478\u7d22\uff0c\u603b\u7ed3\u51fa\u5982\u4e0b\u5b58\u50a8\u8fc7\u7a0b\uff1a\nbegin declare\u00a0f_name\u00a0varchar(100); declare\u00a0b\u00a0int\u00a0default\u00a00;\u00a0\/*\u662f\u5426\u8fbe\u5230\u8bb0\u5f55\u7684\u672b\u5c3e\u63a7\u5236\u53d8\u91cf*\/ --\u00a0\u6ce8\u610f\u4fee\u6539\u4e0b\u9762\u7684\u6570\u636e\u5e93\u540d\u79f0\u00a0wsm_aliyun \u00a0declare\u00a0table_name\u00a0cursor\u00a0for\u00a0SELECT\u00a0TABLE_NAME\u00a0FROM\u00a0information_schema.TABLES\u00a0where\u00a0TABLE_SCHEMA\u00a0=\u00a0&#39;construction_online&#39;; DECLARE\u00a0CONTINUE\u00a0HANDLER\u00a0FOR\u00a0NOT\u00a0FOUND\u00a0SET\u00a0b\u00a0=\u00a01; OPEN\u00a0table_name; REPEAT FETCH\u00a0table_name\u00a0INTO\u00a0f_name;\u00a0\/*\u83b7\u53d6\u7b2c\u4e00\u6761\u8bb0\u5f55*\/ SET\u00a0@STMT\u00a0:=CONCAT(&#34;ALTER\u00a0TABLE\u00a0&#34;,f_name,&#34;\u00a0CONVERT\u00a0TO\u00a0CHARACTER\u00a0SET\u00a0utf8mb4\u00a0COLLATE\u00a0utf8mb4_unicode_ci;&#34;); PREPARE\u00a0STMT\u00a0FROM\u00a0@STMT; EXECUTE\u00a0STMT; --\u00a0INSERT\u00a0into\u00a0TestTable(name)\u00a0VALUES\u00a0(f_name); \u00a0--\u00a0ALTER\u00a0TABLE\u00a0f_name\u00a0CONVERT\u00a0TO\u00a0CHARACTER\u00a0SET\u00a0utf8\u00a0COLLATE\u00a0utf8_general_ci; \u00a0UNTIL\u00a0b\u00a0=\u00a01 END\u00a0REPEAT; close\u00a0table_name; end \u5176\u4e2d\uff0cconstruction_online \u662f\u6570\u636e\u5e93\u540d\uff0cutf8mb4 \u548c utf8mb4_unicode_ci \u4fee\u6539\u6210\u4f60\u60f3\u66ff\u6362\u7684 charset \u548c collation \u5373\u53ef\u3002\n\u6700\u540e\uff1acall \u2026\u2026();\n\u5b8c\u4e8b\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/mysql-update-all-collations\/","summary":"\u4eca\u5929\u9879\u76ee\u90e8\u7f72\u9047\u5230\u4e2a\u5751\uff0c\u4e4b\u524d\u5efa\u6570\u636e\u5e93\u7684\u65f6\u5019\uff0c\u628a\u6240\u6709\u7684 collation \u90fd\u5199\u6210\u4e86 utf8\uff0c\u5728\u6d4b\u8bd5\u670d\u52a1\u5668\u4e0a\u4e5f\u6ca1\u600e\u4e48\u6ce8\u610f\uff0c\u90e8\u7f72\u6b63\u5f0f\u670d\u52a1\u5668\u679c\u65ad\u7528 mb4\uff0c\u6545\u9700\u8981\u4fee\u6539\u4e0a\u767e\u4e2a\u5b57\u6bb5\u7684 collation\u3002\n\u6839\u636e\u4e00\u6b21\u53ef\u4ee5\uff0c\u4e24\u6b21\u80fd\u5fcd\uff0c\u4e09\u6b21\u7edd\u5bf9\u4e0d\u884c\u7684\u61d2\u4eba\u539f\u5219 orz\uff0c\u51b3\u5b9a\u5199\u4e2a\u811a\u672c\u5b9e\u73b0\u4e00\u952e\u4fee\u6539\uff0c\u5e9f\u8bdd\u4e0d\u591a\u8bf4\u5148\u53bb\u7f51\u4e0a\u627e\u4e86\u4e2a\u8f6e\u5b50\u3002\nreferer:\u00a0https:\/\/my.oschina.net\/xuqiang\/blog\/507629\n\u7ecf\u8fc7\u4e00\u756a\u4fee\u6539\u548c\u6478\u7d22\uff0c\u603b\u7ed3\u51fa\u5982\u4e0b\u5b58\u50a8\u8fc7\u7a0b\uff1a\nbegin declare\u00a0f_name\u00a0varchar(100); declare\u00a0b\u00a0int\u00a0default\u00a00;\u00a0\/*\u662f\u5426\u8fbe\u5230\u8bb0\u5f55\u7684\u672b\u5c3e\u63a7\u5236\u53d8\u91cf*\/ --\u00a0\u6ce8\u610f\u4fee\u6539\u4e0b\u9762\u7684\u6570\u636e\u5e93\u540d\u79f0\u00a0wsm_aliyun \u00a0declare\u00a0table_name\u00a0cursor\u00a0for\u00a0SELECT\u00a0TABLE_NAME\u00a0FROM\u00a0information_schema.","title":"MySQL \u6279\u91cf\u66f4\u65b0\u6240\u6709\u5b57\u6bb5 Collation"},{"content":"\u6b64\u5904\u4e0d\u8003\u8651\u786c\u4ef6\uff0c\u6211\u4eec\u505a PaaS\u3002\n\u9996\u5148\u4e91\u670d\u52a1\uff0c\u8d1f\u8f7d\u5747\u8861\u00a0+\u00a02 \u5230 3 \u53f0\u670d\u52a1\u5668\uff0c\u5176\u4e2d\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u91c7\u7528\u5bf9\u8c61\u5b58\u50a8\uff0c\u8fd9\u6837\u53ef\u4ee5\u5927\u91cf\u8282\u7701\u670d\u52a1\u5668\u5e26\u5bbd\uff0c\u5916\u9762\u518d\u5957\u4e00\u5c42 CDN\uff0c\u53ef\u4ee5\u4fdd\u8bc1\u79d2\u5f00\uff1b\u6570\u636e\u5e93\u91c7\u7528\u72ec\u7acb\u7684\u6570\u636e\u5e93\u670d\u52a1\u5668\uff0c\u4e91\u670d\u52a1\u63d0\u4f9b\u5546\u5927\u591a\u5728\u5e95\u5c42\u5b9e\u73b0\u4e86\u70ed\u5907\uff0c\u51fa\u95ee\u9898\u7684\u6982\u7387\u5f88\u5c0f\uff1b\u53e6\u5916\uff0c\u5728\u4e0a\u9762\u7684\u57fa\u7840\u4e0a\u518d\u52a0\u4e0a\u524d\u540e\u7aef\u5206\u79bb\uff0c\u524d\u7aef\u4ee3\u7801\u4e5f\u5168\u90e8\u8dd1\u5728\u5bf9\u8c61\u5b58\u50a8\u91cc\uff0cWeb \u670d\u52a1\u5668\u53ef\u4ee5\u8fbe\u5230\u53ea\u201c\u8ba1\u7b97\u201d\u7684\u76ee\u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\u53ea\u63d0\u4f9b\u63a5\u53e3\u670d\u52a1\u3002 \u53e6\u5916\u4e3a\u4e86\u9632\u6b62\u653b\u51fb\uff0c\u53ef\u4ee5\u5957\u4e09\u5c42\u9632\u5fa1\uff0c\u4e00\u5c42\u5728 DNS \u89e3\u6790\uff0c\u6302\u6389\u4e86\u7acb\u9a6c\u89e3\u6790\u5230\u7b2c\u4e8c\u53f0\uff0c\u7b2c\u4e8c\u5c42\u5728\u4e91\u670d\u52a1\u63d0\u4f9b\u5546\uff0c\u8d2d\u4e70\u5355\u72ec\u7684\u9632\u5fa1\u670d\u52a1\uff0c\u7b2c\u4e09\u5c42\u5728 WEB\uff0c\u76d1\u6d4b\u5230\u653b\u51fb\u7684\u65f6\u5019\u81ea\u52a8\u5bf9\u67d0\u4e00\u4e2a IP \u8fd4\u56de 502\u3002\n\u7136\u540e\u518d\u6765\u8bf4\u6570\u636e\u5e93\u3001\u8bed\u8a00\u548c\u6846\u67b6\u3002\n\u6570\u636e\u5e93\u91c7\u53d6\u4f18\u52bf\u4e92\u8865\uff0cMongoDB \u9002\u5408\u65e5\u5fd7\uff0c\u4f46\u662f\u4e0d\u9002\u5408\u5173\u952e\u6570\u636e\u7684\u5b58\u50a8\uff0cRedis \u9002\u5408\u505a\u67d0\u4e9b\u6570\u636e\u7684\u7f13\u5b58\uff0c\u4f8b\u5982\u6d88\u606f\u961f\u5217\u3001\u70ed\u5ea6 Top10 \u7b49\uff0c\u800c MySQL\/MariaDB \u5219\u662f\u4f5c\u4e3a\u6700\u7ec8\u7684\u6570\u636e\u5b58\u50a8\uff0c\u4e3a\u5565\u6211\u524d\u9762\u76f4\u63a5\u628a MyISAM \u780d\u6389\u4e86\uff0c\u5c31\u662f\u56e0\u4e3a MySQL \u5728\u8fd9\u4e2a\u67b6\u6784\u91cc\u672c\u8eab\u5c31\u662f\u505a\u4e3a\u201c\u6700\u7ec8 boss\u201d\u5b58\u4e00\u4e9b\u5173\u952e\u6570\u636e\u7684\uff0c\u8981\u5c3d\u6700\u5927\u53ef\u80fd\u4fdd\u8bc1\u4e0d\u51fa\u95ee\u9898\uff0c\u800c\u8981\u8ffd\u6c42\u6548\u7387\u3001\u6570\u636e\u4e00\u81f4\u6027\u76f8\u5bf9\u6765\u8bf4\u65e0\u5173\u7d27\u8981\u7684\u65e5\u5fd7\u8fd9\u4e9b\u5c31\u4ea4\u7ed9 MongoDB \u53bb\u505a\u5427\u3002 \u524d\u9762\u8bf4\u7684\u6570\u636e\u5e93\u91c7\u7528\u5355\u72ec\u7684\u670d\u52a1\u5668\uff0c\u4e5f\u662f\u4e3a\u4e86\u8fd9\u4e2a\u539f\u56e0\uff0c\u4e0d\u540c\u7684\u9700\u6c42\u91c7\u7528\u4e0d\u540c\u7684\u6570\u636e\u5e93\uff0c\u8dd1\u5728\u4e0d\u540c\u670d\u52a1\u5668\u3002\n\u8bed\u8a00\uff0c\u8fd8\u662f\u90a3\u5c31\u8bdd\u8bed\u8a00\u6ca1\u6709\u597d\u574f\uff0c\u53ea\u6709\u9002\u4e0d\u9002\u5408\u3002PHP \u505a Web \u670d\u52a1\uff0cNode.JS \u5199\u4e00\u4e9b\u201c\u903b\u8f91\u5c11\u3001\u8c03\u7528\u6b21\u6570\u9891\u7e41\u201d\u7684 API \u518d\u9002\u5408\u4e0d\u8fc7\uff0c\u800c\u6838\u5fc3\u3001\u8ba1\u7b97\u91cf\u91cd\u7684\u4e1c\u897f\uff0c\u5c31\u4ea4\u7ed9\u4e00\u4e9b\u7f16\u8bd1\u578b\u8bed\u8a00\u53bb\u505a\u5427\u3002\n\u6846\u67b6\uff0c\u8fd9\u91cc\u53ea\u8bf4 PHP\uff0cLaravel \u505a Web\uff0cPhalApi \u505a\u63a5\u53e3\u4e0d\u9519\uff0c\u81ea\u52a8\u51fa\u63a5\u53e3\u6587\u6863\uff0c\u652f\u6301\u5355\u5143\u6d4b\u8bd5\uff0c\u540c\u65f6\u53c8\u6bd4\u8f83\u8f7b\u91cf\uff0c\u907f\u514d\u4e86 Laravel \u6027\u80fd\u8c03\u4f18\u7684\u95ee\u9898\u3002\u4f46\u901a\u5e38\u60c5\u51b5\u4e0b Laravel \u771f\u7684\u7528\u5728\u5de5\u51b5\uff0c\u6709\u4e9b\u4e1c\u897f\u8fd8\u662f\u8981\u8fdb\u884c\u201c\u4f18\u5316\u201d\u7684\uff0c\u8fd9\u91cc\u6253\u5f15\u53f7\u7684\u539f\u56e0\uff0c\u662f\u60f3\u8bf4\u6b64\u5904\u4e0d\u662f\u771f\u6b63\u7684\u4f18\u5316\uff0c\u800c\u662f\u4e00\u79cd\u628a Laravel \u8c03\u6574\u5230\u751f\u4ea7\u73af\u5883\u6a21\u5f0f\u7684\u8fc7\u7a0b\uff0c\u672c\u8eab Laravel \u7684\u6548\u7387\u5176\u5b9e\u4e0d\u5dee\uff0c\u53ea\u662f\u88ab\u4e0d\u4f1a\u7528\u7684\u4eba\u4e00\u76f4\u8dd1\u5728\u8c03\u8bd5\u6a21\u5f0f\u7f62\u4e86\u3002\u8fd9\u65b9\u9762\u7f51\u7edc\u4e0a\u6587\u7ae0\u4e0d\u5c11\uff0c\u4e0d\u591a\u8bf4\u4e86\u3002\n\u8fd9\u5927\u6982\u5c31\u662f\u4e00\u4e2a\u57fa\u672c\u5b8c\u5584\u7684\u6574\u5957\u7cfb\u7edf\u6240\u5fc5\u5907\u7684\u51e0\u9879\uff0c\u5176\u5b9e\u8fd8\u6709\u5f88\u591a\u5f88\u72c2\u62fd\u9177\u70ab\u540a\u70b8\u5929\u7684\u65b0\u6280\u672f\/\u65b9\u6848\u6ca1\u6709\u63d0\u5230\uff0c\u6700\u7ec8\u60f3\u8bf4\u7684\u5c31\u4e00\u53e5\u8bdd\uff1a\u5982\u679c\u4e0a\u9762\u8fd9\u4e00\u6574\u5957\u4e0b\u6765\u8fd8\u625b\u4e0d\u4f4f\u4e1a\u52a1\u91cf\uff0c\u90a3\u5c31\u7838\u94b1\u4e70\u66f4\u591a\u670d\u52a1\u5668\u5427\u3002\n\u6bd5\u7adf\u4e0a\u65b0\u6280\u672f\u662f\u6709\u66f4\u5927\u7684\u4ee3\u4ef7\u7684\u3002\n","permalink":"https:\/\/wi1dcard.dev\/posts\/lims-tech-stack\/","summary":"\u6b64\u5904\u4e0d\u8003\u8651\u786c\u4ef6\uff0c\u6211\u4eec\u505a PaaS\u3002\n\u9996\u5148\u4e91\u670d\u52a1\uff0c\u8d1f\u8f7d\u5747\u8861\u00a0+\u00a02 \u5230 3 \u53f0\u670d\u52a1\u5668\uff0c\u5176\u4e2d\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u91c7\u7528\u5bf9\u8c61\u5b58\u50a8\uff0c\u8fd9\u6837\u53ef\u4ee5\u5927\u91cf\u8282\u7701\u670d\u52a1\u5668\u5e26\u5bbd\uff0c\u5916\u9762\u518d\u5957\u4e00\u5c42 CDN\uff0c\u53ef\u4ee5\u4fdd\u8bc1\u79d2\u5f00\uff1b\u6570\u636e\u5e93\u91c7\u7528\u72ec\u7acb\u7684\u6570\u636e\u5e93\u670d\u52a1\u5668\uff0c\u4e91\u670d\u52a1\u63d0\u4f9b\u5546\u5927\u591a\u5728\u5e95\u5c42\u5b9e\u73b0\u4e86\u70ed\u5907\uff0c\u51fa\u95ee\u9898\u7684\u6982\u7387\u5f88\u5c0f\uff1b\u53e6\u5916\uff0c\u5728\u4e0a\u9762\u7684\u57fa\u7840\u4e0a\u518d\u52a0\u4e0a\u524d\u540e\u7aef\u5206\u79bb\uff0c\u524d\u7aef\u4ee3\u7801\u4e5f\u5168\u90e8\u8dd1\u5728\u5bf9\u8c61\u5b58\u50a8\u91cc\uff0cWeb \u670d\u52a1\u5668\u53ef\u4ee5\u8fbe\u5230\u53ea\u201c\u8ba1\u7b97\u201d\u7684\u76ee\u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\u53ea\u63d0\u4f9b\u63a5\u53e3\u670d\u52a1\u3002 \u53e6\u5916\u4e3a\u4e86\u9632\u6b62\u653b\u51fb\uff0c\u53ef\u4ee5\u5957\u4e09\u5c42\u9632\u5fa1\uff0c\u4e00\u5c42\u5728 DNS \u89e3\u6790\uff0c\u6302\u6389\u4e86\u7acb\u9a6c\u89e3\u6790\u5230\u7b2c\u4e8c\u53f0\uff0c\u7b2c\u4e8c\u5c42\u5728\u4e91\u670d\u52a1\u63d0\u4f9b\u5546\uff0c\u8d2d\u4e70\u5355\u72ec\u7684\u9632\u5fa1\u670d\u52a1\uff0c\u7b2c\u4e09\u5c42\u5728 WEB\uff0c\u76d1\u6d4b\u5230\u653b\u51fb\u7684\u65f6\u5019\u81ea\u52a8\u5bf9\u67d0\u4e00\u4e2a IP \u8fd4\u56de 502\u3002\n\u7136\u540e\u518d\u6765\u8bf4\u6570\u636e\u5e93\u3001\u8bed\u8a00\u548c\u6846\u67b6\u3002\n\u6570\u636e\u5e93\u91c7\u53d6\u4f18\u52bf\u4e92\u8865\uff0cMongoDB \u9002\u5408\u65e5\u5fd7\uff0c\u4f46\u662f\u4e0d\u9002\u5408\u5173\u952e\u6570\u636e\u7684\u5b58\u50a8\uff0cRedis \u9002\u5408\u505a\u67d0\u4e9b\u6570\u636e\u7684\u7f13\u5b58\uff0c\u4f8b\u5982\u6d88\u606f\u961f\u5217\u3001\u70ed\u5ea6 Top10 \u7b49\uff0c\u800c MySQL\/MariaDB \u5219\u662f\u4f5c\u4e3a\u6700\u7ec8\u7684\u6570\u636e\u5b58\u50a8\uff0c\u4e3a\u5565\u6211\u524d\u9762\u76f4\u63a5\u628a MyISAM \u780d\u6389\u4e86\uff0c\u5c31\u662f\u56e0\u4e3a MySQL \u5728\u8fd9\u4e2a\u67b6\u6784\u91cc\u672c\u8eab\u5c31\u662f\u505a\u4e3a\u201c\u6700\u7ec8 boss\u201d\u5b58\u4e00\u4e9b\u5173\u952e\u6570\u636e\u7684\uff0c\u8981\u5c3d\u6700\u5927\u53ef\u80fd\u4fdd\u8bc1\u4e0d\u51fa\u95ee\u9898\uff0c\u800c\u8981\u8ffd\u6c42\u6548\u7387\u3001\u6570\u636e\u4e00\u81f4\u6027\u76f8\u5bf9\u6765\u8bf4\u65e0\u5173\u7d27\u8981\u7684\u65e5\u5fd7\u8fd9\u4e9b\u5c31\u4ea4\u7ed9 MongoDB \u53bb\u505a\u5427\u3002 \u524d\u9762\u8bf4\u7684\u6570\u636e\u5e93\u91c7\u7528\u5355\u72ec\u7684\u670d\u52a1\u5668\uff0c\u4e5f\u662f\u4e3a\u4e86\u8fd9\u4e2a\u539f\u56e0\uff0c\u4e0d\u540c\u7684\u9700\u6c42\u91c7\u7528\u4e0d\u540c\u7684\u6570\u636e\u5e93\uff0c\u8dd1\u5728\u4e0d\u540c\u670d\u52a1\u5668\u3002","title":"\u5b9e\u9a8c\u5ba4\u6280\u672f\u65b9\u6848\u89e3\u6790"},{"content":"\u8bde\u751f\u2014\u20142017\/08\/24 \u56e2\u961f\u521d\u671f\u9047\u5230\u4e86\u4e00\u4e9b\u95ee\u9898\u3002\n  \u6280\u672f\u80fd\u529b\u826f\u83a0\u4e0d\u9f50\uff1b\n  \u77e5\u8bc6\u9762\u592a\u7a84\uff0c\u53ea\u4e86\u89e3\u81ea\u5df1\u6240\u5b66\u7684\u9886\u57df\uff1b\n  \u540c\u4e00\u95ee\u9898\u9700\u8981\u91cd\u590d\u8bb2\u89e3\u3001\u57f9\u8bad\uff1b\n  \u95ee\u9898\u5f97\u4e0d\u5230\u603b\u7ed3\uff0c\u65e0\u6cd5\u52a0\u6df1\u5370\u8c61\uff1b\n  \u2026\u2026\n  \u4e8e\u662f\uff0c\u672c\u7ad9\u524d\u8eab\u8bde\u751f\u2014\u2014\u6912\u56fe\u6280\u672f\u535a\u5ba2\u3002\n\u5f53\u65f6\u9009\u62e9\u535a\u5ba2\u7cfb\u7edf\u7ea0\u7ed3\u4e86\u5f88\u4e45\uff0c\u591a\u4eba\u3001\u6743\u9650\u3001\u6613\u4e0a\u624b\uff0c\u8fd9\u4e09\u70b9\u662f\u5fc5\u4e0d\u53ef\u5c11\u7684\u6807\u51c6\u3002\n\u6dd8\u6c70\u6389 Typecho\uff0femlog \u7b49\u4ea7\u54c1\uff0c\u5269\u4e0b Z-Blog PHP \u548c WordPress \u53ef\u4f9b\u9009\u62e9\uff1b\n\u6700\u540e\uff0c\u672c\u7740\u7b80\u5355\u6613\u7528\u7684\u6807\u51c6\uff0c\u51b3\u5b9a\u91c7\u7528\u56fd\u4ea7\u7684 ZBP\u3002\n\u6539\u7248 \u4e24\u4e2a\u6708\u524d\u7684\u6280\u672f\u535a\u5ba2\u8fd8\u53ea\u662f\u4e2a\u96cf\u5f62\uff0c\u4ec5\u7528\u4e8e\u5927\u5bb6\u5728\u5185\u90e8\u6280\u672f\u4ea4\u6d41\u5206\u4eab\u3001\u81ea\u6211\u603b\u7ed3\u7ecf\u9a8c\u65b9\u4fbf\u65e5\u540e\u67e5\u8be2\u3002\n\u540e\u6765\uff0c\u6162\u6162\u5199\u7684\u6587\u7ae0\u591a\u4e86\u8d77\u6765\uff0c\u95ee\u9898\u4e5f\u9010\u6e10\u6d6e\u73b0\uff1a\n  \u6837\u5f0f\u592a\u201c\u7b80\u7ea6\u201d\uff1b\n  \u6ca1\u6709 Markdown \u7f16\u8f91\u5668\uff1b\n  \u529f\u80fd\u7f3a\u5931\uff1b\n  \u2026\u2026\n  \u4e8e\u662f\uff0c\u5c31\u5f00\u59cb\u4e86\u586b\u5751\u4e4b\u8def\u3002\n\u73b0\u72b6 \u76ee\u524d\uff0c\u660e\u663e\u7684\u95ee\u9898\u5df2\u7ecf\u57fa\u672c\u4fee\u590d\u5b8c\u6210\uff1b\u4f46\u51e1\u4e8b\u6ca1\u6709\u7edd\u5bf9\u7684\u5b8c\u7f8e\uff0c\u6211\u4eec\u4f9d\u65e7\u5728\u4e0d\u65ad\u5b8c\u5584\u4e2d\uff0c\u4efb\u4f55\u95ee\u9898\u60a8\u90fd\u53ef\u4ee5\u5728\u4e0b\u65b9\u7559\u8a00\uff0c\u6211\u4eec\u4f1a\u5c3d\u81ea\u5df1\u6240\u80fd\u7ef4\u62a4\u597d\u56e2\u961f\u535a\u5ba2\u3002\n\u672a\u6765 \u5e0c\u671b\u5982\u4eca\u3001\u4ee5\u53ca\u672a\u6765\uff0c\u8fd9\u91cc\u4f1a\u6210\u4e3a\u6211\u4eec\u56e2\u961f\u4e00\u5f20\u5927\u5bb6\u5171\u6709\u7684\u201c\u540d\u7247\u201d\uff0c\u5bf9\u5185\u662f\u6280\u672f\u4ea4\u6d41\u7684\u5e73\u53f0\uff0c\u5bf9\u5916\u662f\u56e2\u961f\u7684\u95e8\u9762\u3002\n\u5171\u52c9\u3002\n\u2014\u2014 \u8239\u6b4c\n","permalink":"https:\/\/wi1dcard.dev\/posts\/started-here\/","summary":"\u8bde\u751f\u2014\u20142017\/08\/24 \u56e2\u961f\u521d\u671f\u9047\u5230\u4e86\u4e00\u4e9b\u95ee\u9898\u3002\n  \u6280\u672f\u80fd\u529b\u826f\u83a0\u4e0d\u9f50\uff1b\n  \u77e5\u8bc6\u9762\u592a\u7a84\uff0c\u53ea\u4e86\u89e3\u81ea\u5df1\u6240\u5b66\u7684\u9886\u57df\uff1b\n  \u540c\u4e00\u95ee\u9898\u9700\u8981\u91cd\u590d\u8bb2\u89e3\u3001\u57f9\u8bad\uff1b\n  \u95ee\u9898\u5f97\u4e0d\u5230\u603b\u7ed3\uff0c\u65e0\u6cd5\u52a0\u6df1\u5370\u8c61\uff1b\n  \u2026\u2026\n  \u4e8e\u662f\uff0c\u672c\u7ad9\u524d\u8eab\u8bde\u751f\u2014\u2014\u6912\u56fe\u6280\u672f\u535a\u5ba2\u3002","title":"\u6700\u521d\u7684\u8d77\u70b9"}]