├── .github
└── workflows
│ └── test-for-dev.yml
├── LICENSE
├── README.md
├── images
├── 1.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
└── 6.png
└── speedtest.sh
/.github/workflows/test-for-dev.yml:
--------------------------------------------------------------------------------
1 | name: Test for sh-dev
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - main
7 | - sh-dev
8 | jobs:
9 | test:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v4
14 | with:
15 | repository: 'i-abc/Speedtest'
16 | ref: 'sh-dev'
17 | - name: Test
18 | run: |
19 | sed -i 's)sleep 0.1)sleep 10)' speedtest.sh
20 | bash speedtest.sh <<<'18'
21 | test-with-debug:
22 | needs: test
23 | runs-on: ubuntu-latest
24 | steps:
25 | - name: Checkout
26 | uses: actions/checkout@v4
27 | with:
28 | repository: 'i-abc/Speedtest'
29 | ref: 'sh-dev'
30 | - name: Test
31 | run: |
32 | sed -i 's)sleep 0.1)sleep 10)' speedtest.sh
33 | bash speedtest.sh --debug <<<'18'
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 多功能测速脚本
2 |
3 | 兼容 [speedtest-cli](https://www.speedtest.net/zh-Hans/apps/cli)、[bim-core](https://github.com/veoco/bim-core)、[speedtest-go](https://github.com/showwin/speedtest-go)、[librespeed-cli](https://github.com/librespeed/speedtest-cli)、[iperf3](https://github.com/esnet/iperf)。
4 |
5 | 脚本自带丰富的测试项目任君挑选,使用者还能自定义想要的测试项目。
6 |
7 | 目录:👉 [效果展示](https://github.com/i-abc/Speedtest#效果展示)、[使用方法](https://github.com/i-abc/Speedtest#使用方法)、[基本功能](https://github.com/i-abc/Speedtest#基本功能)、[进阶功能](https://github.com/i-abc/Speedtest#进阶功能)
8 |
9 | # 效果展示
10 |
11 |
12 |
13 | 大陆三网+教育网 IPv4 多线程测速 (点击展开或收起)
14 |
15 | ✈️ 测试服务器:Azure 东京
16 |
17 | ```
18 | ------------------------ 多功能 自更新 测速脚本 ------------------------
19 | Version : v2023-09-07
20 | Usage : bash <(curl -sL bash.icu/speedtest)
21 | GitHub : https://github.com/i-abc/speedtest
22 | ------------------------------------------------------------------------
23 | 大陆三网+教育网 IPv4 多线程测速,v2023-09-07
24 | ------------------------------------------------------------------------
25 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
26 | 最近的测速点 8201.26 Mbps 883.80 Mbps 1.97 ms 0.09 ms
27 | 电信 天津 3616.50 Mbps 961.05 Mbps 68.72 ms 0.22 ms
28 | 电信 甘肃兰州 13.85 Mbps 759.77 Mbps 63.59 ms 2.06 ms
29 | 电信 四川成都 11.87 Mbps 812.11 Mbps 163.53 ms 10.54 ms
30 | 电信 安徽合肥 5G 3807.94 Mbps 961.02 Mbps 38.43 ms 0.46 ms
31 | 电信 江苏镇江 5G 4863.40 Mbps 960.81 Mbps 36.36 ms 0.60 ms
32 | 电信 湖南长沙 5G 2807.66 Mbps 952.72 Mbps 67.41 ms 0.92 ms
33 | 电信 江苏连云港 5G 4310.71 Mbps 44.88 Mbps 34.83 ms 0.23 ms
34 | 移动 北京 2632.46 Mbps 955.66 Mbps 122.76 ms 0.17 ms
35 | 移动 甘肃兰州 6.41 Mbps 932.02 Mbps 136.94 ms 8.23 ms
36 | 移动 广东深圳 11.13 Mbps 653.17 Mbps 187.76 ms 154.31 ms
37 | 移动 浙江杭州 5G 2894.64 Mbps 705.73 Mbps 85.02 ms 0.12 ms
38 | 移动 陕西西安 5G 2685.48 Mbps 957.27 Mbps 133.28 ms 0.30 ms
39 | 联通 江苏无锡 3876.50 Mbps 960.85 Mbps 36.55 ms 0.19 ms
40 | 联通 四川成都 25.62 Mbps 355.90 Mbps 62.15 ms 0.30 ms
41 | 联通 福建福州 5501.38 Mbps 失败 53.53 ms 0.19 ms
42 | 联通 辽宁沈阳 2323.80 Mbps 581.46 Mbps 66.04 ms 0.80 ms
43 | 联通 海南三亚 4729.78 Mbps 923.30 Mbps 76.86 ms 0.05 ms
44 | 联通 湖南长沙 5G 141.74 Mbps 960.81 Mbps 76.18 ms 1.33 ms
45 | 联通 河南郑州 5G 39.73 Mbps 960.70 Mbps 51.34 ms 0.29 ms
46 | 广电 重庆 1.88 Mbps 23.92 Mbps 87.10 ms 0.45 ms
47 | 教育网 江苏苏州 1.07 Mbps 19.53 Mbps 147.53 ms 209.28 ms
48 | 教育网 北京 220.15 Mbps 366.71 Mbps 85.82 ms 0.02 ms
49 | 教育网 上海 241.95 Mbps 262.00 Mbps 197.73 ms 0.79 ms
50 | 教育网 江苏南京 619.21 Mbps 502.79 Mbps 110.64 ms 0.39 ms
51 | 教育网 安徽合肥 失败 635.71 Mbps 106.36 ms 1.16 ms
52 | ------------------------------------------------------------------------
53 | 当前时间:2023-09-08 09:30:48 CST
54 | 北京时间: 2023-09-08 09:30:48+08:00
55 | ------------------------------------------------------------------------
56 | ```
57 |
58 |
59 |
60 |
61 |
62 | 大陆三网+教育网 IPv4 单线程测速
63 |
64 | ✈️ 测试服务器:Azure 东京
65 |
66 | ```
67 | ------------------------ 多功能 自更新 测速脚本 ------------------------
68 | Version : v2023-09-07
69 | Usage : bash <(curl -sL bash.icu/speedtest)
70 | GitHub : https://github.com/i-abc/speedtest
71 | ------------------------------------------------------------------------
72 | 大陆三网+教育网 IPv4 单线程测速,v2023-09-07
73 | ------------------------------------------------------------------------
74 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
75 | 电信 天津 386.20 Mbps 443.30 Mbps 51.80 ms 4.30 ms
76 | 电信 甘肃兰州 2.40 Mbps 239.10 Mbps 66.40 ms 41.00 ms
77 | 电信 四川成都 0.30 Mbps 6.90 Mbps 125.70 ms 252.40 ms
78 | 电信 湖南长沙 5G 304.00 Mbps 307.80 Mbps 58.00 ms 7.20 ms
79 | 电信 安徽合肥 5G 334.40 Mbps 628.40 Mbps 39.50 ms 0.50 ms
80 | 电信 浙江宁波 5G 235.60 Mbps 581.30 Mbps 37.70 ms 7.50 ms
81 | 电信 江苏镇江 5G 632.40 Mbps 662.10 Mbps 36.60 ms 7.50 ms
82 | 电信 江苏连云港 5G 520.50 Mbps 0.80 Mbps 35.00 ms 1.70 ms
83 | 移动 北京 609.30 Mbps 244.90 Mbps 120.00 ms 2.80 ms
84 | 移动 甘肃兰州 失败 443.50 Mbps 123.50 ms 31.20 ms
85 | 移动 广东深圳 0.50 Mbps 184.90 Mbps 93.20 ms 2.90 ms
86 | 移动 浙江杭州 5G 243.60 Mbps 183.40 Mbps 83.20 ms 2.00 ms
87 | 移动 陕西西安 5G 706.60 Mbps 99.40 Mbps 106.00 ms 8.10 ms
88 | 联通 江苏无锡 失败 失败 35.60 ms 23.20 ms
89 | 联通 四川成都 8.10 Mbps 5.70 Mbps 62.70 ms 1.90 ms
90 | 联通 福建福州 347.80 Mbps 284.70 Mbps 56.20 ms 12.50 ms
91 | 联通 辽宁沈阳 162.50 Mbps 211.50 Mbps 65.70 ms 10.30 ms
92 | 联通 海南三亚 15.00 Mbps 335.40 Mbps 74.40 ms 17.30 ms
93 | 联通 湖南长沙 5G 2.30 Mbps 461.10 Mbps 49.00 ms 3.90 ms
94 | 联通 河南郑州 5G 19.20 Mbps 940.60 Mbps 49.10 ms 8.10 ms
95 | 广电 重庆 0.60 Mbps 31.50 Mbps 86.10 ms 1.20 ms
96 | 教育网 江苏苏州 0.30 Mbps 1.00 Mbps 140.50 ms 37.10 ms
97 | 电信 宿迁 自建 跳过 443.00 Mbps 跳过 跳过
98 | ------------------------------------------------------------------------
99 | 当前时间:2023-09-08 09:15:11 CST
100 | 北京时间: 2023-09-08 09:15:11+08:00
101 | ------------------------------------------------------------------------
102 | ```
103 |
104 |
105 |
106 |
107 |
108 | 各大洲 IPV4 八线程测速
109 |
110 | ✈️ 测试服务器:Hetzner 德国
111 |
112 | ```
113 | ------------------------ 多功能 自更新 测速脚本 ------------------------
114 | Version : v2023-09-08
115 | Usage : bash <(curl -sL bash.icu/speedtest)
116 | GitHub : https://github.com/i-abc/speedtest
117 | ------------------------------------------------------------------------
118 | 各大洲 IPv4 八线程测速,v2023-09-08
119 | ------------------------------------------------------------------------
120 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
121 | 美国 纽约 1770.00 Mbps 1975.00 Mbps 跳过 跳过
122 | 美国 阿什本 934.00 Mbps 237.00 Mbps 跳过 跳过
123 | 美国 查尔斯顿 1682.00 Mbps 1665.00 Mbps 跳过 跳过
124 | 德国 柏林 13530.00 Mbps 14451.00 Mbps 跳过 跳过
125 | 瑞士 温特图尔 11221.00 Mbps 11167.00 Mbps 跳过 跳过
126 | 丹麦 哥本哈根 6578.00 Mbps 3671.00 Mbps 跳过 跳过
127 | 瑞士 沙夫豪森 9301.00 Mbps 8279.00 Mbps 跳过 跳过
128 | 荷兰 阿姆斯特丹 9271.00 Mbps 9257.00 Mbps 跳过 跳过
129 | 印度 苏里 9330.00 Mbps 9314.00 Mbps 跳过 跳过
130 | 亚洲 新加坡 976.00 Mbps 3.44 Mbps 跳过 跳过
131 | 亚洲 乌兹别克斯坦 1942.00 Mbps 2055.00 Mbps 跳过 跳过
132 | 大洋洲 澳大利亚 164.00 Mbps 398.00 Mbps 跳过 跳过
133 | 大洋洲 新喀里多尼亚 164.00 Mbps 132.00 Mbps 跳过 跳过
134 | 非洲 突尼斯 912.00 Mbps 827.00 Mbps 跳过 跳过
135 | 非洲 毛里求斯 751.00 Mbps 36.40 Mbps 跳过 跳过
136 | ------------------------------------------------------------------------
137 | 当前时间:2023-09-08 14:29:19 UTC
138 | 北京时间: 2023-09-08 22:29:19+08:00
139 | ------------------------------------------------------------------------
140 | ```
141 |
142 |
143 |
144 |
145 |
146 | IPV4 UDP 可用性测试
147 |
148 | ✈️ 测试服务器:Azure 东京
149 |
150 | ```
151 | ------------------------ 多功能 自更新 测速脚本 ------------------------
152 | Version : v2023-09-04
153 | Usage : bash <(curl -sL bash.icu/speedtest)
154 | GitHub : https://github.com/i-abc/speedtest
155 | ------------------------------------------------------------------------
156 | UDP IPv4 单线程测速,v2023-09-04
157 | 机房UDP限速,结果仅代表UDP是否可用
158 | ------------------------------------------------------------------------
159 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
160 | 联通/电信 宿迁 自建 1.05 Mbps 1.05 Mbps 跳过 跳过
161 | 美国 阿什本 1.05 Mbps 1.05 Mbps 跳过 跳过
162 | 美国 亚特兰大 1.05 Mbps 1.05 Mbps 跳过 跳过
163 | 美国 查尔斯顿 1.04 Mbps 1.05 Mbps 跳过 跳过
164 | ------------------------------------------------------------------------
165 | 当前时间:2023-09-05 20:19:26 CST
166 | 北京时间: 2023-09-05 20:19:26+08:00
167 | ------------------------------------------------------------------------
168 | ```
169 |
170 |
171 |
172 |
173 |
174 | 大陆教育网 IPv4 多线程测速
175 |
176 | ✈️ 测试服务器:Azure 东京
177 |
178 | ```
179 | ------------------------ 多功能 自更新 测速脚本 ------------------------
180 | Version : v2023-09-04
181 | Usage : bash <(curl -sL bash.icu/speedtest)
182 | GitHub : https://github.com/i-abc/speedtest
183 | ------------------------------------------------------------------------
184 | 大陆教育网 IPv4 测速,v2023-09-05
185 | ------------------------------------------------------------------------
186 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
187 | 教育网 北京 254.49 Mbps 374.56 Mbps 81.18 ms 0.27 ms
188 | 教育网 上海 245.49 Mbps 273.71 Mbps 200.36 ms 4.05 ms
189 | 教育网 江苏南京 630.06 Mbps 515.28 Mbps 112.09 ms 0.12 ms
190 | 教育网 安徽合肥 0.00 Mbps 641.16 Mbps 105.18 ms 0.37 ms
191 | ------------------------------------------------------------------------
192 | 当前时间:2023-09-06 11:21:18 CST
193 | 北京时间: 2023-09-06 11:21:18+08:00
194 | ------------------------------------------------------------------------
195 | ```
196 |
197 |
198 |
199 |
200 |
201 | 大陆教育网 IPv6 多线程测速
202 |
203 | ✈️ 测试服务器:Hetzner 德国
204 |
205 | ```
206 | ------------------------ 多功能 自更新 测速脚本 ------------------------
207 | Version : v2023-09-08
208 | Usage : bash <(curl -sL bash.icu/speedtest)
209 | GitHub : https://github.com/i-abc/speedtest
210 | ------------------------------------------------------------------------
211 | 大陆教育网 IPv6 测速,v2023-09-08
212 | ------------------------------------------------------------------------
213 | 测速节点 下载/Mbps 上传/Mbps 延迟/ms 抖动/ms
214 | 教育网 上海 220.51 Mbps 217.85 Mbps 257.27 ms 0.29 ms
215 | 教育网 江苏南京 210.13 Mbps 156.00 Mbps 260.73 ms 0.46 ms
216 | 教育网 安徽合肥 失败 229.02 Mbps 255.55 ms 1.09 ms
217 | 教育网 辽宁沈阳 失败 8.89 Mbps 241.00 ms 失败
218 | ------------------------------------------------------------------------
219 | 当前时间:2023-09-08 14:36:12 UTC
220 | 北京时间: 2023-09-08 22:36:12+08:00
221 | ------------------------------------------------------------------------
222 | ```
223 |
224 |
225 |
226 | # 使用方法
227 |
228 |
229 |
230 | ```bash
231 | bash <(curl -sL bash.icu/speedtest)
232 | ```
233 |
234 | 或
235 |
236 | ```bash
237 | bash <(curl -sL https://raw.githubusercontent.com/i-abc/Speedtest/main/speedtest.sh)
238 | ```
239 |
240 | # 基本功能
241 |
242 | 脚本自带丰富的测试项目:
243 |
244 | 0. [自定义测速节点](https://github.com/i-abc/Speedtest/tree/main#进阶功能)
245 | 1. 大陆三网+教育网 IPv4 多线程测速
246 | 2. 大陆三网+教育网 IPv4 单线程测速
247 | 3. 大陆教育网 IPv6 多线程测速
248 | 4. 各大洲 IPV4 八线程测速
249 | 5. 各大洲 IPV6 八线程测速
250 | 6. IPV4 UDP 可用测试测试
251 | 7. 大陆教育网 IPv4 多线程测速
252 | 8. 大陆电信 IPv4 多线程测速
253 | 9. 大陆电信 IPv4 单线程测速
254 | 10. 大陆移动 IPv4 多线程测速
255 | 11. 大陆移动 IPv4 单线程测速
256 | 12. 大陆联通 IPv4 多线程测速
257 | 13. 大陆联通 IPv4 单线程测速
258 | 14. 各大洲 IPV4 32线程测速
259 | 15. 各大洲 IPV4 单线程测速
260 | 16. 各大洲 IPV6 32线程测速
261 | 17. 各大洲 IPV6 单线程测速
262 |
263 | 持续更新中……
264 |
265 | # 进阶功能
266 |
267 | 自定义自己想要的测试项目,很简单的。
268 |
269 | 我们会有两张表,节点表 (必需)、节点集合表 (非必需)。
270 |
271 | ## 节点表 (必需)
272 |
273 | 节点表分为四个区域,分别是提示语区、测试类型区、节点名区、测试参数区;后三区组成三列,彼此之间用英文逗号 `,` 分隔,如下图所示:
274 |
275 | 
276 |
277 | ### 示例
278 |
279 | ```
280 | 节点表 模板示例,v2023-09-08
281 | speedtest-cli ,联通 郑州 cli ,-o 5gtest.shangdu.com
282 | bim-core ,联通 郑州 bimc ,http://5gtest.shangdu.com:8080/download http://5gtest.shangdu.com:8080/upload
283 | speedtest-go ,联通 郑州 go ,--custom-url http://5gtest.shangdu.com:8080/speedtest/upload.php --ping-mode http
284 | speedtest-go ,联通 郑州 八线程 ,--custom-url http://5gtest.shangdu.com:8080/speedtest/upload.php --ping-mode http -t 8
285 | speedtest-go ,联通 郑州 只测上传 ,--custom-url http://5gtest.shangdu.com:8080/speedtest/upload.php --ping-mode http --no-download
286 | librespeed-cli,教育 南京 ,--server-json https://jihulab.com/i-abc/speedtest/-/raw/node/china-education.json --server 1 --no-icmp
287 | librespeed-cli,教育 南京 只测上传 ,--server-json https://jihulab.com/i-abc/speedtest/-/raw/node/china-education.json --server 1 --no-icmp --no-download
288 | iperf3 ,联通 宿迁 只测上传 ,-c 103.239.244.210 -p 22222
289 | iperf3 ,联通 宿迁 只测下载 ,-c 103.239.244.210 -p 22222 -R
290 | iperf3 ,联通 宿迁 八线程 ,-c 103.239.244.210 -p 22222 -P 8
291 | iperf3 ,联通 宿迁 测UDP ,-c 103.239.244.210 -p 22222 -u
292 | iperf3 ,联通 宿迁 测双向 ,-c 103.239.244.210 -p 22222 --up-and-down
293 | ```
294 |
295 | ### 1区:提示语区 (可选)
296 |
297 | 提示语位于节点表开头,可以在这里写上任何话,比如使用说明、备注、自家广告等,当然也可以不写。
298 |
299 | ### 3区:节点名区
300 |
301 | 显而易见,这里就是写对应节点的名字。
302 |
303 | 由于中英文字符编码很难处理,所以如果想要输出美观还得麻烦大家敲空格对齐,当然不对齐对测试无影响。
304 |
305 | 提示语区、节点名区会直接反映到输出,它们在输出、节点表之间的关系如下图所示:
306 |
307 | 
308 |
309 | ### 2区:测试类型区
310 |
311 | 我们有五种类型,分别是 [speedtest-cli](https://www.speedtest.net/zh-Hans/apps/cli)、[bim-core](https://github.com/veoco/bim-core)、[speedtest-go](https://github.com/showwin/speedtest-go)、[librespeed-cli](https://github.com/librespeed/speedtest-cli)、[iperf3](https://github.com/esnet/iperf),选一种即可,每种都有不同的特点,具体说明请往下看。
312 |
313 | 这部分加空格对齐不是必须的,不加对输出无任何影响,当然像我一样的强迫症可以加空格对齐。
314 |
315 | ### 4区:测试参数区
316 |
317 | 我们脚本兼容 [speedtest-cli](https://www.speedtest.net/zh-Hans/apps/cli)、[bim-core](https://github.com/veoco/bim-core)、[speedtest-go](https://github.com/showwin/speedtest-go)、[librespeed-cli](https://github.com/librespeed/speedtest-cli)、[iperf3](https://github.com/esnet/iperf),我挑选了部分对测试有用的参数应用到了脚本里,大家可以按需使用。
318 |
319 | | **类型** | **测速点提供商** | **只单向测速** | **指定IPv6测速** | **单连接测速** | **UDP测试** | **不使用 ICMP Ping** | **指定测试时长** |
320 | |----------------|---------------|-----------|---------------|-----------|-----------|-------------------|---------------|
321 | | speedtest-cli | speedtest.net | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
322 | | bim-core | speedtest.net | ❌ | ✔️ | ✔️ | ❌ | ❌ | ❌ |
323 | | speedtest-go | speedtest.net | ✔️ | ❌ | ✔️ | ❌ | ✔️ | ❌ |
324 | | librespeed-cli | 公共、自建 | ✔️ | ✔️ | ❌ | ❌ | ✔️ | ✔️ |
325 | | iperf3 | 公共、自建 | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
326 |
327 | **使用 [speedtest.net](https://www.speedtest.net) 时,多连接测速推荐 speedtest-cli、单连接测速推荐 bim-core。**
328 |
329 | #### 1️⃣ speedtest-cli
330 |
331 | [speedtest-cli](https://www.speedtest.net/zh-Hans/apps/cli):[speedtest.net](https://www.speedtest.net) 官方 CLI,功能单一。
332 |
333 | | 参数 | 作用 | 示例 |
334 | |----|------------|-----------------------|
335 | | -s value | 通过 id 指定节点 | -s 36646 |
336 | | -o value | 通过域名指定节点 | -o 5gtest.shangdu.com |
337 |
338 | `-s` 和 `-o` 二选一,`-o` 后面参数为纯域名,不含 http(s)、端口号;推荐 `-o`。
339 |
340 | 节点 id、域名可在 [https://www.speedtest.net/api/ios-config.php](https://www.speedtest.net/api/ios-config.php) 查阅。
341 |
342 | 例如:``,则 id 为 `36646`,域名为 `5gtest.shangdu.com`。
343 |
344 | #### 2️⃣ bim-core
345 |
346 | [bim-core](https://github.com/veoco/bim-core):针对 [speedtest.net](https://www.speedtest.net) 开发的第三方,功能较多,能实现单线程、指定 IPv6 测速。
347 |
348 | | 参数 | 作用 | 示例 |
349 | |-------------------|----------------------------|------------------------------------------------------------------|
350 | | download_url | 节点的下载链接 | http://5gtest.shangdu.com:8080/download |
351 | | upload_url | 节点的上传链接 | http://5gtest.shangdu.com:8080/upload |
352 | | -m | 启用八线程测速 | -m |
353 | | -6 | 仅使用 IPv6 | -6 |
354 |
355 | download_url 和 upload_url 两者都要,且 download_url 在前、upload_url 在后,含 http(s)、端口、分别以 `/download`、`/upload` 结尾。
356 |
357 | 节点链接可在 [https://www.speedtest.net/api/ios-config.php](https://www.speedtest.net/api/ios-config.php) 查阅。
358 |
359 | 例如:``,则 download_url 为 `http://5gtest.shangdu.com:8080/download`,则 upload_url 为 `http://5gtest.shangdu.com:8080/upload`。
360 |
361 | #### 3️⃣ speedtest-go
362 |
363 | [speedtest-go](https://github.com/showwin/speedtest-go):针对 [speedtest.net](https://www.speedtest.net) 开发的第三方,功能较多,能实现指定线程、禁用某方向测速。
364 |
365 | | 参数 | 作用 | 示例 |
366 | |-------------------|----------------------------|------------------------------------------------------------------|
367 | | -s value | 通过 id 指定节点 | -s 36646 |
368 | | --custom-url value | 通过链接指定节点 | --custom-url http://5gtest.shangdu.com:8080/speedtest/upload.php |
369 | | -t value | 设置并发连接数 | -t 8 |
370 | | -m | 启用多服务器模式 | -m |
371 | | --no-download | 禁用下载测试 | --no-download |
372 | | --no-upload | 禁用上传测试 | --no-upload |
373 | | --ping-mode value | 选择一种 Ping 的方法 | --ping-mode http |
374 |
375 | `-s` 和 `--custom-url` 二选一,`--custom-url` 后面参数为完整链接,含 http(s)、端口、以 `/upload.php` 结尾;推荐 `--custom-url`。
376 |
377 | `--ping-mode http` 推荐加上。
378 |
379 | 节点 id、链接可在 [https://www.speedtest.net/api/ios-config.php](https://www.speedtest.net/api/ios-config.php) 查阅。
380 |
381 | 例如:``,则 id 为 `36646`,链接为 `http://5gtest.shangdu.com:8080/speedtest/upload.php`。
382 |
383 | #### 4️⃣ librespeed-cli
384 |
385 | [librespeed-cli](https://github.com/librespeed/speedtest-cli)
386 |
387 | | 参数 | 作用 | 示例 |
388 | |---------------|-----------------------------------------------|-----------------------------------------------------------------------------------|
389 | | --server-json value | 远程 JSON 的服务端列表 | --server-json https://jihulab.com/i-abc/speedtest/-/raw/node/china-education.json |
390 | | --local-json value | 本地 JSON 的服务端列表 | --local-json /root/librespeed.json |
391 | | --server value | 通过 JSON 中的 ID 指定服务端 | --server 1 |
392 | | -4 | 仅使用 IPv4 (默认 false) | -4 |
393 | | -6 | 仅使用 IPv6 (默认 false) | -6 |
394 | | --no-download | 禁用下载测试 (默认 false) | --no-download |
395 | | --no-upload | 禁用上传测试 (默认 false) | --no-upload |
396 | | --no-icmp | 不使用 ICMP Ping。ICMP 在 Linux 下工作不稳定 (默认 false) | --no-icmp |
397 | | --duration | 测试的持续时间 (秒) (默认 15) | --duration 20 |
398 |
399 | `--no-icmp` 推荐加上。
400 |
401 | 现成的、优质的 librespeed 服务端较少,而且需要自己写服务端列表 JSON,JSON 写法参照 [官方](https://github.com/librespeed/speedtest-cli#use-a-custom-backend-server-list);如果是个人搭建测速、个人使用,推荐 iperf3。
402 |
403 | #### 5️⃣ iperf3
404 |
405 | [iperf3](https://github.com/esnet/iperf)
406 |
407 | | 参数 | 作用 | 示例 |
408 | |---------------|---------------------|--------------------|
409 | | -c ip/host | 指定服务端 | -c 103.239.244.210 |
410 | | -p value | 指定服务端端口 | -p 22222 |
411 | | -P value | 设置并发连接数 | -P 8 |
412 | | -t value | 测试的持续时间 (秒) (默认 10) | -t 20 |
413 | | -O value | 前 N 秒的数据不计入最终结果 | -O 3 |
414 | | -R | 反向模式,服务器发送、客户端接收 | -R |
415 | | -4 | 仅使用 IPv4 | -4 |
416 | | -6 | 仅使用 IPv6 | -6 |
417 | | -u | UDP测试 | -u |
418 | | --up-and-down | 双向测试 (自创选项) | --up-and-down |
419 |
420 | 当服务端端口为默认的 5201 时,`-p` 可不加;`-p` 除了 `-p 22222` 指定一个端口,还能 `-p 5200-5209` 指定一个范围内的端口。
421 |
422 | iperf3 默认是客户端发送、服务端接收,也就是测上传;想测下载可加 `-R` 开启反向模式;但 iperf3 只支持单向,所以脚本里自创了 `--up-and-down` 选项,加上后可测双向;`--up-and-down` 与 `-R` 二选一,**且 `--up-and-down` 在本脚本以外的地方不可用,非官方选项**。
423 |
424 | 现成的、优质的 iperf3 服务端很多,可在 [iPerf3 Server List](https://iperf3serverlist.net) 查阅;自建 iperf3 服务端也简单,用包管理器就行了。
425 |
426 | ## 节点集合表 (非必需)
427 |
428 | 当你有很多节点表时可以组一个节点表合集,如下图所示,当然这不是必需的。
429 |
430 | 
431 |
432 | ### 示例
433 |
434 | ```
435 | 1. 节点示例
436 | /root/GitHub/speedtest/node-template-1.txt
437 | 2. 示例1
438 | /root/GitHub/speedtest/node-template-01.txt
439 | 3. 示例2
440 | /root/GitHub/speedtest/node-template-02.txt
441 | ```
442 |
443 | 每两行为一组,每组中的第一行以序号加英文点 `.` 开头,第二行为节点表链接,链接可为远程 http 或本地绝对路径。
444 |
445 | 节点集合表与输出之间的关系如下图所示:
446 |
447 | 
448 |
449 | ## 使用自定义的表
450 |
451 | 我们现在有了节点表、节点集合表,那么该如何使用呢?
452 |
453 | 只需选择时输入序号 `0`,然后填写链接或本地绝对路径即可;链接为节点表就立即开始测试,链接为节点集合表就还会出现选择节点的提示。
454 |
455 | 
456 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/3.png
--------------------------------------------------------------------------------
/images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/4.png
--------------------------------------------------------------------------------
/images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/5.png
--------------------------------------------------------------------------------
/images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-abc/Speedtest/f959d1fa9a2eb8c4c739cc15f068bd70cf46fb87/images/6.png
--------------------------------------------------------------------------------
/speedtest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ######### 自定义常量 ##########
4 |
5 | _constant() {
6 | script_version="v2024-04-25"
7 | old_IFS="$IFS"
8 | work_dir="./sp-github-i-abc"
9 | node_set=""
10 | node_set_1="https://raw.githubusercontent.com/i-abc/speedtest/node/all-node.txt"
11 | node_set_2="https://asset.bash.icu/https://raw.githubusercontent.com/i-abc/speedtest/node/all-node-mirror.txt"
12 |
13 | # url_1为官方源,url_2为镜像源,皆会进行SHA-256检测
14 |
15 | # speedtest-cli,https://www.speedtest.net/zh-Hans/apps/cli
16 | speedtest_cli_version="1.2.0"
17 | speedtest_cli_tar_x86_64_sha256="5690596c54ff9bed63fa3732f818a05dbc2db19ad36ed68f21ca5f64d5cfeeb7"
18 | speedtest_cli_tar_i386_sha256="9ff7e18dbae7ee0e03c66108445a2fb6ceea6c86f66482e1392f55881b772fe8"
19 | speedtest_cli_tar_aarch64_sha256="3953d231da3783e2bf8904b6dd72767c5c6e533e163d3742fd0437affa431bd3"
20 | speedtest_cli_tar_armhf_sha256="e45fcdebbd8a185553535533dd032d6b10bc8c64eee4139b1147b9c09835d08d"
21 | speedtest_cli_tar_armel_sha256="629a455a2879224bd0dbd4b36d8c721dda540717937e4660b4d2c966029466bf"
22 | speedtest_cli_tar_url=""
23 | speedtest_cli_tar_url_1="https://install.speedtest.net/app/cli/ookla-speedtest-${speedtest_cli_version}-linux-${speedtest_cli_arch}.tgz"
24 | speedtest_cli_tar_url_2="https://asset.bash.icu/https://raw.githubusercontent.com/i-abc/speedtest/asset/speedtest-cli/v${speedtest_cli_version}/ookla-speedtest-${speedtest_cli_version}-linux-${speedtest_cli_arch}.tgz"
25 |
26 | # bim-core,https://github.com/veoco/bim-core
27 | bim_core_version="0.17.0"
28 | bim_core_tar_x86_64_sha256="109280fbf5a821bc56c2e83b906e65228ebc8436054b2e7861ca6db88f7e0330"
29 | bim_core_tar_aarch64_sha256="fa62357f94050fbb7851d1bbb7e393d8e1301281ce03c43b37dae55cbf08c198"
30 | bim_core_tar_url=""
31 | bim_core_tar_url_1="https://github.com/veoco/bim-core/releases/download/v${bim_core_version}/bimc-${bim_core_arch}-unknown-linux-musl"
32 | bim_core_tar_url_2="https://asset.bash.icu/https://github.com/veoco/bim-core/releases/download/v${bim_core_version}/bimc-${bim_core_arch}-unknown-linux-musl"
33 |
34 | # speedtest-go,https://github.com/showwin/speedtest-go
35 | speedtest_go_version="1.6.11"
36 | speedtest_go_tar_x86_64_sha256="2603cf54513dd770353d66095a30b13d170d225a0a60fc07ee6d5f5a78e15a27"
37 | speedtest_go_tar_i386_sha256="5ec1df89446aab656c0947c9028fa93b40ec83a4132e30b3dad978215103e294"
38 | speedtest_go_tar_arm64_sha256="68b1be4cd6dbbd3d68216a106b578fd2bdf51b8606d3597743aefdb2f0234c24"
39 | speedtest_go_tar_armv7_sha256="f30ba82ac4e6fd967302d505fa7380745d89a4ddcfb72f607b580ef507e5eb0a"
40 | speedtest_go_tar_armv6_sha256="ccdc0a4281c193cccc027e7c2fb2b961e1eb3e4eab1dcf68b46bd0dafd2e895f"
41 | speedtest_go_tar_url=""
42 | speedtest_go_tar_url_1="https://github.com/showwin/speedtest-go/releases/download/v${speedtest_go_version}/speedtest-go_${speedtest_go_version}_Linux_${speedtest_go_arch}.tar.gz"
43 | speedtest_go_tar_url_2="https://asset.bash.icu/https://github.com/showwin/speedtest-go/releases/download/v${speedtest_go_version}/speedtest-go_${speedtest_go_version}_Linux_${speedtest_go_arch}.tar.gz"
44 |
45 | # librespeed-cli,https://github.com/librespeed/speedtest-cli
46 | librespeed_cli_version="1.0.10"
47 | librespeed_cli_tar_amd64_sha256="8e6d020c17e11dba73f0eb8a11f7ae6e3d96cdb307faf3c0ec13aa54e0cba055"
48 | librespeed_cli_tar_386_sha256="0121bd4a21786d5964643b00a4193edfa15389050afe5579a290e67b706ef9eb"
49 | librespeed_cli_tar_arm64_sha256="0ecbb98abb39f17bde2c0efae23f8446f4596c3a824aa6dda9b71723386b03ed"
50 | librespeed_cli_tar_armv7_sha256="b121733b9a18aa646a16393396dd7fe59e8773420a38acb05b91652c4d6cb356"
51 | librespeed_cli_tar_armv6_sha256="def98bbf0e79805411bca312e9e6bcddd12cd0abf4e6584a3ae05aa20c762b64"
52 | librespeed_cli_tar_url=""
53 | librespeed_cli_tar_url_1="https://github.com/librespeed/speedtest-cli/releases/download/v${librespeed_cli_version}/librespeed-cli_${librespeed_cli_version}_linux_${librespeed_cli_arch}.tar.gz"
54 | librespeed_cli_tar_url_2="https://asset.bash.icu/https://github.com/librespeed/speedtest-cli/releases/download/v${librespeed_cli_version}/librespeed-cli_${librespeed_cli_version}_linux_${librespeed_cli_arch}.tar.gz"
55 |
56 | # 配色
57 | red='\033[1;31m'
58 | green='\033[1;32m'
59 | yellow='\033[1;33m'
60 | blue='\033[1;34m'
61 | purple='\033[1;35m'
62 | cyan='\033[1;36m'
63 | endc='\033[0m'
64 | }
65 |
66 | ########## 进度条 ###########
67 | _show_progress_bar() {
68 | local bar="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
69 | local i=0
70 | local n="${#bar}"
71 | while sleep 0.1; do
72 | printf "\r ${green}测试进行中 %s${endc} " "${bar:i++%n:1}"
73 | done
74 | }
75 |
76 | ########## 横幅 ###########
77 |
78 | _print_banner_1() {
79 | echo "------------------------ 多功能 自更新 测速脚本 ------------------------"
80 | echo -e " Version : ${green}${script_version}${endc}"
81 | echo -e " Usage : ${yellow}bash <(curl -sL bash.icu/speedtest)${endc}"
82 | echo -e " GitHub : ${green}https://github.com/i-abc/speedtest${endc}"
83 | printf "%-72s\n" "-" | sed 's)\s)-)g'
84 | }
85 |
86 | _print_banner_2() {
87 | if [ -s "$work_dir"/banner-custom.txt ]; then
88 | cat "$work_dir"/banner-custom.txt
89 | printf "%-72s\n" "-" | sed 's)\s)-)g'
90 | fi
91 | }
92 |
93 | _print_banner_3() {
94 | printf "%-s%-s%-s%-s%-s\n" "测速节点 " "下载/Mbps " "上传/Mbps " "延迟/ms " "抖动/ms"
95 | }
96 |
97 | _print_banner_4() {
98 | printf "%-72s\n" "-" | sed 's)\s)-)g'
99 | echo "系统时间:$(date +"%Y-%m-%d %H:%M:%S %Z")"
100 | echo "北京时间: $(TZ=Asia/Shanghai date +"%Y-%m-%d %H:%M:%S %Z")"
101 | printf "%-72s\n\n" "-" | sed 's)\s)-)g'
102 | }
103 |
104 | ########## 检测是否为 root ##########
105 | _check_user() {
106 | sudo_flag=""
107 | if [[ "${UID}" -eq 0 ]]; then
108 | echo "当前用户是 root"
109 | else
110 | echo "当前用户不是 root"
111 | sudo_flag="sudo"
112 | fi
113 | }
114 |
115 | ########## 确认架构及其对应版本的程序 ##########
116 |
117 | _check_architecture() {
118 | speedtest_cli_arch=""
119 | bim_core_archh=""
120 | speedtest_go_arch=""
121 | librespeed_cli_arch=""
122 | local arch
123 | arch="$(uname -m)"
124 | if [ "$arch" == "x86_64" ]; then
125 | speedtest_cli_arch="x86_64"
126 | bim_core_arch="x86_64"
127 | speedtest_go_arch="x86_64"
128 | librespeed_cli_arch="amd64"
129 | elif [ "$arch" == "i386" ] || [ "$arch" == "i686" ]; then
130 | speedtest_cli_arch="i386"
131 | speedtest_go_arch="i386"
132 | librespeed_cli_arch="386"
133 | elif [ "$arch" == "armv8" ] || [ "$arch" == "armv8l" ] || [ "$arch" == "aarch64" ] || [ "$arch" == "arm64" ]; then
134 | speedtest_cli_arch="aarch64"
135 | bim_core_arch="aarch64"
136 | speedtest_go_arch="arm64"
137 | librespeed_cli_arch="arm64"
138 | elif [ "$arch" == "armv7" ] || [ "$arch" == "armv7l" ]; then
139 | speedtest_cli_arch="armhf"
140 | speedtest_go_arch="armv7"
141 | librespeed_cli_arch="armv7"
142 | elif [ "$arch" == "armv6" ]; then
143 | speedtest_cli_arch="armel"
144 | speedtest_go_arch="armv6"
145 | librespeed_cli_arch="armv6"
146 | fi
147 | }
148 |
149 | ########## 检测地区,指定下载源 ##########
150 |
151 | _check_region() {
152 | loc=$(curl -s -L "https://www.qualcomm.cn/cdn-cgi/trace" | awk -F'=' '/loc/{ print $2 }')
153 | echo "loc: $loc"
154 | if [ -z "$loc" ]; then
155 | echo "使用镜像源"
156 | node_set="$node_set_2"
157 | speedtest_cli_tar_url="$speedtest_cli_tar_url_2"
158 | bim_core_tar_url="$bim_core_tar_url_2"
159 | speedtest_go_tar_url="$speedtest_go_tar_url_2"
160 | librespeed_cli_tar_url="$librespeed_cli_tar_url_2"
161 | elif [ "$loc" != "CN" ]; then
162 | echo "使用默认源"
163 | node_set="$node_set_1"
164 | speedtest_cli_tar_url="$speedtest_cli_tar_url_1"
165 | bim_core_tar_url="$bim_core_tar_url_1"
166 | speedtest_go_tar_url="$speedtest_go_tar_url_1"
167 | librespeed_cli_tar_url="$librespeed_cli_tar_url_1"
168 | else
169 | echo "使用镜像源"
170 | node_set="$node_set_2"
171 | speedtest_cli_tar_url="$speedtest_cli_tar_url_2"
172 | bim_core_tar_url="$bim_core_tar_url_2"
173 | speedtest_go_tar_url="$speedtest_go_tar_url_2"
174 | librespeed_cli_tar_url="$librespeed_cli_tar_url_2"
175 | fi
176 | }
177 |
178 | ########## 检测某软件包是否安装,没安则自动安上,目前只支持RedHat、Debian系 ##########
179 |
180 | _check_package() {
181 | echo "正在检测所需的$1是否安装"
182 | # 检测软件包是否安装
183 | if ! command -v "$1"; then
184 | # 确认包管理器并安装软件包
185 | # RedHat
186 | if command -v dnf; then
187 | ${sudo_flag} dnf install -y "$2"
188 | elif command -v yum; then
189 | ${sudo_flag} yum install -y "$2"
190 | # Debian
191 | elif command -v apt; then
192 | ${sudo_flag} apt install -y "$2"
193 | # Arch Linux
194 | elif command -v pacman; then
195 | ${sudo_flag} pacman -S --noconfirm "$2"
196 | else
197 | echo "本机非RedHat、Debian、Arch Linux"
198 | echo "暂不支持自动安装所需的软件包"
199 | exit 1
200 | fi
201 | # 再次检测软件包是否安装
202 | if ! command -v "$1"; then
203 | echo "自动安装所需的$1失败"
204 | echo "请手动安装$1后再执行本脚本"
205 | exit 1
206 | fi
207 | fi
208 | }
209 |
210 | ########## 创建工作目录 ##########
211 |
212 | _make_dir() {
213 | # 删除可能存在的残余文件
214 | rm -rf "$work_dir"
215 | # 创建目录
216 | mkdir "$work_dir"
217 | }
218 |
219 | ########## 下载程序 ##########
220 |
221 | _download_tar() {
222 | echo "$speedtest_cli_tar_url"
223 | echo "speedtest-cli下载中"
224 | curl --progress-bar -o "$work_dir"/speedtest-cli.tgz -L "$speedtest_cli_tar_url"
225 | echo "$bim_core_tar_url"
226 | echo "bim-core下载中"
227 | [ -n "$bim_core_arch" ] && curl --progress-bar -o "$work_dir"/bim-core -L "$bim_core_tar_url"
228 | echo "$speedtest_go_tar_url"
229 | echo "speedtest-go下载中"
230 | curl --progress-bar -o "$work_dir"/speedtest-go.tar.gz -L "$speedtest_go_tar_url"
231 | echo "$librespeed_cli_tar_url"
232 | echo "librespeed-cli下载中"
233 | curl --progress-bar -o "$work_dir"/librespeed-cli.tar.gz -L "$librespeed_cli_tar_url"
234 | }
235 |
236 | ########## 检测程序的SHA-256 ##########
237 |
238 | _check_tar_sha256() {
239 | local speedtest_cli_tar_download_sha256 bim_core_tar_download_sha256 speedtest_go_tar_download_sha256 librespeed_cli_tar_download_sha256
240 | speedtest_cli_tar_download_sha256=$(sha256sum "$work_dir"/speedtest-cli.tgz | awk '{ print $1 }')
241 | bim_core_tar_download_sha256=$(sha256sum "$work_dir"/bim-core | awk '{ print $1 }')
242 | speedtest_go_tar_download_sha256=$(sha256sum "$work_dir"/speedtest-go.tar.gz | awk '{ print $1 }')
243 | librespeed_cli_tar_download_sha256=$(sha256sum "$work_dir"/librespeed-cli.tar.gz | awk '{ print $1 }')
244 | if [ "$speedtest_cli_tar_download_sha256" != "$(eval "echo \$speedtest_cli_tar_${speedtest_cli_arch}_sha256")" ]; then
245 | printf "${red}%-s${endc}\n" "经检测,speedtest-cli的SHA-256与官方不符,方便的话欢迎到GitHub反馈"
246 | exit 1
247 | fi
248 | if [ "$bim_core_tar_download_sha256" != "$(eval "echo \$bim_core_tar_${bim_core_arch}_sha256")" ] && [ -n "$bim_core_arch" ]; then
249 | printf "${red}%-s${endc}\n" "经检测,bim-core的SHA-256与官方不符,方便的话欢迎到GitHub反馈"
250 | exit 1
251 | fi
252 | if [ "$speedtest_go_tar_download_sha256" != "$(eval "echo \$speedtest_go_tar_${speedtest_go_arch}_sha256")" ]; then
253 | printf "${red}%-s${endc}\n" "经检测,speedtest-go的SHA-256与官方不符,方便的话欢迎到GitHub反馈"
254 | exit 1
255 | fi
256 | if [ "$librespeed_cli_tar_download_sha256" != "$(eval "echo \$librespeed_cli_tar_${librespeed_cli_arch}_sha256")" ]; then
257 | printf "${red}%-s${endc}\n" "经检测,librespeed-cli的SHA-256与官方不符,方便的话欢迎到GitHub反馈"
258 | exit 1
259 | fi
260 | }
261 |
262 | ########## 解压程序 ##########
263 |
264 | _unzip_tar() {
265 | tar -xf "$work_dir"/speedtest-cli.tgz -C "$work_dir"
266 | tar -xf "$work_dir"/speedtest-go.tar.gz -C "$work_dir"
267 | tar -xf "$work_dir"/librespeed-cli.tar.gz -C "$work_dir"
268 | chmod +x "$work_dir"/bim-core
269 | }
270 |
271 | ########## 获取节点列表 ##########
272 |
273 | _get_node_list() {
274 | # 节点集合
275 | local node_url node_selection_1 node_selection_2 node_selection_3 first_line second_line
276 | _print_banner_1
277 | echo -e "${blue}↓ ↓ ↓ ↓ ↓ ↓ 测速节点列表 ↓ ↓ ↓ ↓ ↓ ↓${endc}"
278 | echo -e "0. \033[1m自定义测速节点\033[0m"
279 | curl -s -L "$node_set" | awk '$0!~/http/{print}'
280 | printf "${yellow}%-s${endc}" "请输入您想选择的节点序号: "
281 | read -r node_selection_1
282 | # 某类节点
283 | if [ "$node_selection_1" -ne 0 ]; then
284 | node_url=$(curl -s -L "$node_set" | awk -F. "\$1== $node_selection_1 { getline; print }")
285 | curl -o "$work_dir"/all-node.txt -L "$node_url"
286 | elif [ "$node_selection_1" -eq 0 ]; then
287 | printf "${yellow}%-s${endc}" "请输入您的自定义节点链接(http或本地绝对路径): "
288 | read -r node_url_custom
289 | # 判断自定义节点是网络链接还是本地文件
290 | # 网络,http
291 | if [[ "$node_url_custom" =~ \w{0}https?:// ]]; then
292 | first_line="$(curl -s -L "$node_url_custom" | awk -F'.' NR==1'{ print $1 }')"
293 | second_line="$(curl -s -L "$node_url_custom" | awk NR==2)"
294 | if [ "$first_line" -eq 1 ] &>/dev/null && echo "$second_line" | grep -q -E "\w{0}https?://" &>/dev/null; then
295 | node_set="$node_url_custom"
296 | curl -s -L "$node_set" | awk '$0!~/http/{print}'
297 | printf "${yellow}%-s${endc}" "请输入您想选择的节点序号: "
298 | read -r node_selection_2
299 | node_url=$(curl -s -L "$node_set" | awk -F. "\$1== $node_selection_2 { getline; print }")
300 | curl -o "$work_dir"/all-node.txt -L "$node_url"
301 | else
302 | node_url="$node_url_custom"
303 | curl -o "$work_dir"/all-node.txt -L "$node_url"
304 | fi
305 | # 本地,绝对路径
306 | elif [[ "$node_url_custom" =~ \w{0}/{1} ]]; then
307 | first_line="$(awk -F'.' NR==1'{ print $1 }' <"$node_url_custom")"
308 | second_line="$(awk NR==2 <"$node_url_custom")"
309 | if [ "$first_line" -eq 1 ] &>/dev/null && echo "$second_line" | grep -q -E "\w{0}/{1}" &>/dev/null; then
310 | node_set="$node_url_custom"
311 | awk '$0!~/^\//{print}' <"$node_set"
312 | printf "${yellow}%-s${endc}" "请输入您想选择的节点序号: "
313 | read -r node_selection_3
314 | node_url="$(awk -F. "\$1== $node_selection_3 { getline; print }" <"$node_set")"
315 | cp -f "$node_url" "$work_dir"/all-node.txt
316 | else
317 | node_url="$node_url_custom"
318 | cp -f "$node_url" "$work_dir"/all-node.txt
319 | fi
320 | fi
321 | fi
322 | }
323 |
324 | ########## 分类节点 ###########
325 |
326 | _classify_node() {
327 | # 总行数
328 | local row_num
329 | row_num=$(wc -l "$work_dir"/all-node.txt | awk '{print $1}')
330 | # 分类
331 | for ((i = 1; i <= row_num; i++)); do
332 | # 第一列
333 | local first_column
334 | first_column=$(awk -F, NR==${i}'{print $1}' "$work_dir"/all-node.txt)
335 | # speedtest-cli
336 | if [[ "$first_column" =~ "speedtest-cli" ]]; then
337 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/speedtest-cli-node.txt
338 | # bim-core
339 | elif [[ "$first_column" =~ "bim-core" ]] && [ -n "$bim_core_arch" ]; then
340 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/bim-core-node.txt
341 | # speedtest-go
342 | elif [[ "$first_column" =~ "speedtest-go" ]]; then
343 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/speedtest-go-node.txt
344 | # librespeed-cli
345 | elif [[ "$first_column" =~ "librespeed-cli" ]]; then
346 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/librespeed-cli-node.txt
347 | # iperf3
348 | elif [[ "$first_column" =~ "iperf3" ]]; then
349 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/iperf3-node.txt
350 | # 自定义的横幅
351 | elif [ "$first_column" != "" ]; then
352 | awk NR==${i} "$work_dir"/all-node.txt >>"$work_dir"/banner-custom.txt
353 | fi
354 | done
355 | }
356 |
357 | ########## speedtest-cli ##########
358 |
359 | _speedtest_cli_test() {
360 | # speedtest-cli的选项、参数
361 | awk -F, '{ print $3 }' "$work_dir"/speedtest-cli-node.txt >"$work_dir"/speedtest-cli-option.txt
362 | _filter_option_speedtest_cli "$work_dir"/speedtest-cli-option.txt "$work_dir"/speedtest-cli-option-filter.txt
363 | # speedtest-cli测试、输出
364 | option_para=""
365 | count="1"
366 | while IFS= read -r option_para; do
367 | IFS="$old_IFS"
368 | local node_name latency jitter download upload
369 | local download_c="15" upload_c="15" latency_c="13" jitter_c="13"
370 | # speedtest-cli测试
371 | _show_progress_bar &
372 | bar_pid="$!" && disown "$bar_pid"
373 | timeout --foreground 70 ${work_dir}/speedtest --accept-license --accept-gdpr -f json-pretty ${option_para} >${work_dir}/speedtest-cli-${count}.json 2>${work_dir}/speedtest-cli-${count}-error.json
374 | kill "$bar_pid" 2>/dev/null && printf "\r"
375 | # speedtest-cli输出
376 | if [ -s "$work_dir"/speedtest-cli-"$count".json ]; then
377 | # 节点名称
378 | node_name=$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/speedtest-cli-node.txt)
379 | # 延迟,ms
380 | latency="$(awk -F': |,' '/ping/{ getline; getline; print $2 }' "$work_dir"/speedtest-cli-"$count".json)"
381 | _check_num "$latency" || latency=" 失败"
382 | _check_num "$latency" || latency_c="15"
383 | _check_num "$latency" && latency="$(printf "%.2f" "$latency") ms"
384 | # 抖动,ms
385 | jitter="$(awk -F': |,' '/ping/{ getline; print $2 }' "$work_dir"/speedtest-cli-"$count".json)"
386 | _check_num "$jitter" || jitter=" 失败"
387 | _check_num "$jitter" || jitter_c="15"
388 | _check_num "$jitter" && jitter="$(printf "%.2f" "$jitter") ms"
389 | # 下载速度,bps->Mbps
390 | download="$(awk -F': |,' '/download/{ getline; print $2 }' "$work_dir"/speedtest-cli-"$count".json)"
391 | _check_num "$download" || download=" 失败"
392 | _check_num "$download" || download_c="17"
393 | _check_num "$download" && download="$(echo "scale=2; $download / 125000" | bc)" && download="$(printf "%.2f" "$download") Mbps"
394 | # 上传速度,bps->Mbps
395 | upload="$(awk -F': |,' '/upload/{ getline; print $2 }' "$work_dir"/speedtest-cli-"$count".json)"
396 | _check_num "$upload" || upload=" 失败"
397 | _check_num "$upload" || upload_c="17"
398 | _check_num "$upload" && upload="$(echo "scale=2; $upload / 125000" | bc)" && upload="$(printf "%.2f" "$upload") Mbps"
399 | # 输出结果
400 | [ -s "$work_dir"/speedtest-cli-"$count".json ] && _check_output
401 | fi
402 | if grep -q "Too many requests received" "$work_dir"/speedtest-cli-"$count"-error.json; then
403 | echo "测速次数过多,暂时被限制,请过一段时间后再进行测试"
404 | break
405 | fi
406 | count=$((count + 1))
407 | done <"$work_dir"/speedtest-cli-option-filter.txt
408 | }
409 |
410 | ########## bim-core ##########
411 |
412 | _bim_core_test() {
413 | # bim-core的选项、参数
414 | awk -F, '{ print $3 }' "$work_dir"/bim-core-node.txt >"$work_dir"/bim-core-option.txt
415 | _filter_option_bim_core "$work_dir"/bim-core-option.txt "$work_dir"/bim-core-option-filter.txt
416 | # bim-core测试、输出
417 | option_para=""
418 | count="1"
419 | while IFS= read -r option_para; do
420 | IFS="$old_IFS"
421 | local node_name latency jitter download upload
422 | local download_c="15" upload_c="15" latency_c="13" jitter_c="13"
423 | # bim-core测试
424 | _show_progress_bar &
425 | bar_pid="$!" && disown "$bar_pid"
426 | timeout --foreground 70 ${work_dir}/bim-core ${option_para} >${work_dir}/bim-core-${count}.json 2>${work_dir}/bim-core-${count}-error.json
427 | kill "$bar_pid" 2>/dev/null && printf "\r"
428 | # bim-core输出
429 | if [ -s "$work_dir"/bim-core-"$count".json ]; then
430 | # 节点名称
431 | node_name=$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/bim-core-node.txt)
432 | # 延迟,ms
433 | latency="$(awk '{ print $5 }' "$work_dir"/bim-core-"$count".json | awk -F',' '{ print $1 }')"
434 | _check_num "$latency" || latency=" 失败"
435 | _check_num "$latency" || latency_c="15"
436 | _check_num "$latency" && latency="$(printf "%.2f" "$latency") ms"
437 | # 抖动,ms
438 | jitter="$(awk '{ print $6 }' "$work_dir"/bim-core-"$count".json)"
439 | _check_num "$jitter" || jitter=" 失败"
440 | _check_num "$jitter" || jitter_c="15"
441 | _check_num "$jitter" && jitter="$(printf "%.2f" "$jitter") ms"
442 | # 下载速度
443 | download="$(awk '{ print $3 }' "$work_dir"/bim-core-"$count".json | awk -F',' '{ print $1 }')"
444 | _check_num "$download" || download=" 失败"
445 | _check_num "$download" || download_c="17"
446 | _check_num "$download" && download="$(printf "%.2f" "$download") Mbps"
447 | # 上传速度
448 | upload="$(awk '{ print $1 }' "$work_dir"/bim-core-"$count".json | awk -F',' '{ print $1 }')"
449 | _check_num "$upload" || upload=" 失败"
450 | _check_num "$upload" || upload_c="17"
451 | _check_num "$upload" && upload="$(printf "%.2f" "$upload") Mbps"
452 | # 输出结果
453 | [ -s "$work_dir"/bim-core-"$count".json ] && _check_output
454 | fi
455 | count=$((count + 1))
456 | done <"$work_dir"/bim-core-option-filter.txt
457 | }
458 |
459 | ########## speedtest-go ##########
460 |
461 | _speedtest_go_test() {
462 | # speedtest-go的选项、参数
463 | awk -F, '{ print $3 }' "$work_dir"/speedtest-go-node.txt >"$work_dir"/speedtest-go-option.txt
464 | _filter_option_speedtest_go "$work_dir"/speedtest-go-option.txt "$work_dir"/speedtest-go-option-filter.txt
465 | # speedtest-go测试、输出
466 | option_para=""
467 | count="1"
468 | while IFS= read -r option_para; do
469 | IFS="$old_IFS"
470 | local node_name latency jitter download upload
471 | local download_c="15" upload_c="15" latency_c="13" jitter_c="13"
472 | # speedtest-go测试
473 | _show_progress_bar &
474 | bar_pid="$!" && disown "$bar_pid"
475 | timeout --foreground 70 ${work_dir}/speedtest-go ${option_para} >${work_dir}/speedtest-go-${count}.json 2>${work_dir}/speedtest-go-${count}-error.json
476 | kill "$bar_pid" 2>/dev/null && printf "\r"
477 | # speedtest-go输出
478 | if [ -s "$work_dir"/speedtest-go-"$count".json ] && ! grep -q "Fatal" "$work_dir"/speedtest-go-"$count".json; then
479 | # 节点名称
480 | node_name="$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/speedtest-go-node.txt)"
481 | # 延迟,ms
482 | latency="$(awk -F' |ms|µs' '/Latency/{ print $3 }' "$work_dir"/speedtest-go-"$count".json)"
483 | if awk -F'Latency: ' /Latency/'{ print $2 }' "$work_dir"/speedtest-go-"$count".json | awk -F' Jitter: ' '{ print $1 }' | grep -q µs; then
484 | latency_unit="µs"
485 | elif awk -F'Latency: ' /Latency/'{ print $2 }' "$work_dir"/speedtest-go-"$count".json | awk -F' Jitter: ' '{ print $1 }' | grep -q ms; then
486 | latency_unit="ms"
487 | fi
488 | _check_num "$latency" || latency=" 失败"
489 | _check_num "$latency" || latency_c="15"
490 | _check_num "$latency" && latency="$(printf "%.2f" "$latency") $latency_unit"
491 | # 抖动,ms
492 | jitter="$(awk -F' |ms|µs' '/Jitter/{ print $6 }' "$work_dir"/speedtest-go-"$count".json)"
493 | if awk -F'Jitter: ' /Jitter/'{ print $2 }' "$work_dir"/speedtest-go-"$count".json | awk -F' Min: ' '{ print $1 }' | grep -q µs; then
494 | jitter_unit="µs"
495 | elif awk -F'Jitter: ' /Jitter/'{ print $2 }' "$work_dir"/speedtest-go-"$count".json | awk -F' Min: ' '{ print $1 }' | grep -q ms; then
496 | jitter_unit="ms"
497 | fi
498 | _check_num "$jitter" || jitter=" 失败"
499 | _check_num "$jitter" || jitter_c="15"
500 | _check_num "$jitter" && jitter="$(printf "%.2f" "$jitter") $jitter_unit"
501 | # 下载、上传速度,Mbps
502 | download="$(awk -F' |Mbps' '/Download/{ print $3 }' "$work_dir"/speedtest-go-"$count".json)"
503 | _check_num "$download" || download=" 失败"
504 | _check_num "$download" || download_c="17"
505 | _check_num "$download" && download="$(printf "%.2f" "$download") Mbps"
506 | upload="$(awk -F' |Mbps' '/Upload/{ print $3 }' "$work_dir"/speedtest-go-"$count".json)"
507 | _check_num "$upload" || upload=" 失败"
508 | _check_num "$upload" || upload_c="17"
509 | _check_num "$upload" && upload="$(printf "%.2f" "$upload") Mbps"
510 | _check_option "--no-upload" "$option_para" && upload=" 跳过"
511 | _check_option "--no-upload" "$option_para" && upload_c="17"
512 | _check_option "--no-download" "$option_para" && download=" 跳过"
513 | _check_option "--no-download" "$option_para" && download_c="17"
514 | # 输出结果
515 | [ -s "$work_dir"/speedtest-go-"$count".json ] && _check_output
516 | fi
517 | count=$((count + 1))
518 | done <"$work_dir"/speedtest-go-option-filter.txt
519 | }
520 |
521 | ########## librespeed-cli ##########
522 |
523 | _librespeed_cli_test() {
524 | # librespeed-cli的选项、参数
525 | awk -F, '{ print $3 }' "$work_dir"/librespeed-cli-node.txt >"$work_dir"/lbrespeed-cli-option.txt
526 | _filter_option_librespeed_cli "$work_dir"/lbrespeed-cli-option.txt "$work_dir"/lbrespeed-cli-option-filter.txt
527 | # librespeed-cli测试、输出
528 | option_para=""
529 | count="1"
530 | while IFS= read -r option_para; do
531 | IFS="$old_IFS"
532 | local node_name latency jitter download upload
533 | local download_c="15" upload_c="15" latency_c="13" jitter_c="13"
534 | # librespeed-cli测试
535 | _show_progress_bar &
536 | bar_pid="$!" && disown "$bar_pid"
537 | timeout --foreground 70 ${work_dir}/librespeed-cli --json ${option_para} >${work_dir}/librespeed-cli-${count}.json 2>${work_dir}/librespeed-cli-${count}-error.json
538 | kill "$bar_pid" 2>/dev/null && printf "\r"
539 | # librespeed-cli输出
540 | if [ -s "$work_dir"/librespeed-cli-"$count".json ]; then
541 | # 节点名称
542 | node_name=$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/librespeed-cli-node.txt)
543 | # 延迟,ms
544 | latency="$(awk -F'"ping":' '{ print $2 }' "$work_dir"/librespeed-cli-"$count".json | awk -F',' '{ print $1 }')"
545 | _check_num "$latency" || latency=" 失败"
546 | _check_num "$latency" || latency_c="15"
547 | _check_num "$latency" && latency="$(printf "%.2f" "$latency") ms"
548 | # 抖动,ms
549 | jitter="$(awk -F'"jitter":' '{ print $2 }' "$work_dir"/librespeed-cli-"$count".json | awk -F',' '{ print $1 }')"
550 | _check_num "$jitter" || jitter=" 失败"
551 | _check_num "$jitter" || jitter_c="15"
552 | _check_num "$jitter" && jitter="$(printf "%.2f" "$jitter") ms"
553 | # 下载、上传速度,Mbps
554 | download="$(awk -F'"download":' '{ print $2 }' "$work_dir"/librespeed-cli-"$count".json | awk -F',' '{ print $1 }')"
555 | _check_num "$download" || download=" 失败"
556 | _check_num "$download" || download_c="17"
557 | _check_num "$download" && download="$(printf "%.2f" "$download") Mbps"
558 | upload="$(awk -F'"upload":' '{ print $2 }' "$work_dir"/librespeed-cli-"$count".json | awk -F',' '{ print $1 }')"
559 | _check_num "$upload" || upload=" 失败"
560 | _check_num "$upload" || upload_c="17"
561 | _check_num "$upload" && upload="$(printf "%.2f" "$upload") Mbps"
562 | _check_option "--no-upload" "$option_para" && upload=" 跳过"
563 | _check_option "--no-upload" "$option_para" && upload_c="17"
564 | _check_option "--no-download" "$option_para" && download=" 跳过"
565 | _check_option "--no-download" "$option_para" && download_c="17"
566 | # 输出结果
567 | [ -s "$work_dir"/librespeed-cli-"$count".json ] && _check_output
568 | fi
569 | count=$((count + 1))
570 | done <"$work_dir"/lbrespeed-cli-option-filter.txt
571 | }
572 |
573 | ########## iperf3 ##########
574 |
575 | _iperf3_test() {
576 | # iperf3的选项、参数
577 | awk -F',' '{ print $3 }' "$work_dir"/iperf3-node.txt >"$work_dir"/iperf3-option.txt
578 | _filter_option_iperf3 "$work_dir"/iperf3-option.txt "$work_dir"/iperf3-option-filter.txt
579 | # iperf3测试、输出
580 | option_para=""
581 | count="1"
582 | while IFS= read -r option_para; do
583 | IFS="$old_IFS"
584 | local node_name download upload latency jitter
585 | local download_c="15" upload_c="15" latency_c="13" jitter_c="13"
586 | # iperf3测试
587 | if _check_option "--up-and-down" "$option_para"; then
588 | # 双向
589 | option_para="$(echo "$option_para" | awk -F'--up-and-down' '{ print $1 $2 }')"
590 | # 节点名称
591 | node_name=$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/iperf3-node.txt)
592 | # 延迟,ms
593 | latency=" 跳过"
594 | latency_c="15"
595 | # 抖动,ms
596 | jitter=" 跳过"
597 | jitter_c="15"
598 | # 上传
599 | local i_busy
600 | for ((i_busy = 1; i_busy <= 65; i_busy++)); do
601 | _show_progress_bar &
602 | bar_pid="$!" && disown "$bar_pid"
603 | timeout --foreground 70 iperf3 -f m ${option_para} >${work_dir}/iperf3-${count}.json 2>${work_dir}/iperf3-${count}-error.json
604 | kill "$bar_pid" 2>/dev/null && printf "\r"
605 | if grep -q "busy" "$work_dir"/iperf3-"$count"-error.json; then
606 | sleep 0.5
607 | fi
608 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
609 | break
610 | fi
611 | done
612 | # 上传速度,Mbps
613 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
614 | upload="$(awk '{ rows[NR] = $0 } END{ print rows[NR-3] }' "$work_dir"/iperf3-"$count".json | awk -F'Bytes ' '{ print $2 }' | awk '{ print $1 }')"
615 | _check_num "$upload" || upload=" 失败"
616 | _check_num "$upload" || upload_c="17"
617 | _check_num "$upload" && upload="$(printf "%.2f" "$upload") Mbps"
618 | else
619 | upload=" 跳过" && upload_c="17"
620 | fi
621 | # 下载
622 | for ((i_busy = 1; i_busy <= 65; i_busy++)); do
623 | _show_progress_bar &
624 | bar_pid="$!" && disown "$bar_pid"
625 | timeout --foreground 70 iperf3 -f m -R ${option_para} >${work_dir}/iperf3-${count}.json 2>${work_dir}/iperf3-${count}-error.json
626 | kill "$bar_pid" 2>/dev/null && printf "\r"
627 | if grep -q "busy" "$work_dir"/iperf3-"$count"-error.json; then
628 | sleep 0.5
629 | fi
630 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
631 | break
632 | fi
633 | done
634 | # 下载速度,Mbps
635 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
636 | download="$(awk '{ rows[NR] = $0 } END{ print rows[NR-2] }' "$work_dir"/iperf3-"$count".json | awk -F'Bytes ' '{ print $2 }' | awk '{ print $1 }')"
637 | _check_num "$download" || download=" 失败"
638 | _check_num "$download" || download_c="17"
639 | _check_num "$download" && download="$(printf "%.2f" "$download") Mbps"
640 | else
641 | upload=" 跳过" && upload_c="17"
642 | fi
643 | # 输出结果
644 | [ -s "$work_dir"/iperf3-"$count".json ] && _check_output
645 | else
646 | # 单向
647 | for ((i_busy = 1; i_busy <= 65; i_busy++)); do
648 | _show_progress_bar &
649 | bar_pid="$!" && disown "$bar_pid"
650 | timeout --foreground 70 iperf3 -f m ${option_para} >${work_dir}/iperf3-${count}.json 2>${work_dir}/iperf3-${count}-error.json
651 | kill "$bar_pid" 2>/dev/null && printf "\r"
652 | if grep -q "busy" "$work_dir"/iperf3-"$count"-error.json; then
653 | sleep 0.5
654 | fi
655 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
656 | break
657 | fi
658 | done
659 | # iperf3输出
660 | if [ -s "$work_dir"/iperf3-"$count".json ]; then
661 | # 节点名称
662 | node_name=$(awk -F, NR=="$count"'{ print $2 }' "$work_dir"/iperf3-node.txt)
663 | # 延迟,ms
664 | latency=" 跳过"
665 | latency_c="15"
666 | # 抖动,ms
667 | jitter=" 跳过"
668 | jitter_c="15"
669 | # 下载、上传速度,Mbps
670 | upload="$(awk '{ rows[NR] = $0 } END{ print rows[NR-3] }' "$work_dir"/iperf3-"$count".json | awk -F'Bytes ' '{ print $2 }' | awk '{ print $1 }')"
671 | _check_num "$upload" || upload=" 失败"
672 | _check_num "$upload" || upload_c="17"
673 | _check_num "$upload" && upload="$(printf "%.2f" "$upload") Mbps"
674 | download="$(awk '{ rows[NR] = $0 } END{ print rows[NR-2] }' "$work_dir"/iperf3-"$count".json | awk -F'Bytes ' '{ print $2 }' | awk '{ print $1 }')"
675 | _check_num "$download" || download=" 失败"
676 | _check_num "$download" || download_c="17"
677 | _check_num "$download" && download="$(printf "%.2f" "$download") Mbps"
678 | _check_option "-R" "$option_para" && upload=" 跳过"
679 | _check_option "-R" "$option_para" && upload_c="17"
680 | _check_option "-R" "$option_para" || download=" 跳过"
681 | _check_option "-R" "$option_para" || download_c="17"
682 | # 输出结果
683 | [ -s "$work_dir"/iperf3-"$count".json ] && _check_output
684 | fi
685 | fi
686 | count=$((count + 1))
687 | done <"$work_dir"/iperf3-option-filter.txt
688 | }
689 |
690 | ########## 整理选项、参数 ##########
691 |
692 | # 不带参数的选项,包括-/--
693 | _filter_option_0_para() {
694 | if [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "$1" ] || [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "$2" ]; then
695 | line_output="$line_output $1"
696 | fi
697 | }
698 |
699 | # 带一个参数的选项,包括-/--
700 | _filter_option_1_para() {
701 | if [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "$1" ] || [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "$2" ]; then
702 | column_count=$((column_count + 1))
703 | line_output="$line_output $1 $(echo "$line_input" | awk "{ print $"$column_count" }")"
704 | fi
705 | }
706 |
707 | # bim-core专用,处理为链接的参数
708 | _filter_option_bim_core_1() {
709 | if [[ "$(echo "$line_input" | awk "{ print $"$column_count" }")" =~ http ]]; then
710 | line_output="$line_output $(echo "$line_input" | awk "{ print $"$column_count" }")"
711 | fi
712 | }
713 |
714 | # iperf3专用,处理-p选项
715 | _filter_option_iperf3_1() {
716 | local port
717 | if [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "-p" ] || [ "$(echo "$line_input" | awk "{ print $"$column_count" }")" == "--port" ]; then
718 | column_count=$((column_count + 1))
719 | port=$(echo "$line_input" | awk "{ print $"$column_count" }")
720 | if [[ "$port" =~ ^[0-9]+$ ]]; then
721 | # 一个端口
722 | line_output="$line_output $1 $port"
723 | else
724 | # 多个端口,随机一个
725 | port=$(shuf -n 1 -i $port)
726 | line_output="$line_output $1 $port"
727 | fi
728 | fi
729 | }
730 |
731 | # speedtest-cli
732 | _filter_option_speedtest_cli() {
733 | local line_input line_output column_count column_all_count
734 | local file_input="$1" file_output="$2"
735 | while IFS= read -r line_input; do
736 | IFS="$old_IFS"
737 | line_output=""
738 | column_all_count="$(echo "$line_input" | awk '{ print NF }')"
739 | for ((column_count = 1; column_count <= column_all_count; column_count++)); do
740 | _filter_option_1_para -s --server-id
741 | _filter_option_1_para -o --host
742 | done
743 | echo "$line_output" >>"$file_output"
744 | done <"$file_input"
745 | }
746 |
747 | # bim-core
748 | _filter_option_bim_core() {
749 | local line_input line_output column_count column_all_count
750 | local file_input="$1" file_output="$2"
751 | while IFS= read -r line_input; do
752 | IFS="$old_IFS"
753 | line_output=""
754 | column_all_count="$(echo "$line_input" | awk '{ print NF }')"
755 | for ((column_count = 1; column_count <= column_all_count; column_count++)); do
756 | _filter_option_1_para -6 --ipv6
757 | _filter_option_1_para -m --multi
758 | _filter_option_bim_core_1
759 | done
760 | echo "$line_output" >>"$file_output"
761 | done <"$file_input"
762 | }
763 |
764 | # speedtest-go
765 | _filter_option_speedtest_go() {
766 | local line_input line_output column_count column_all_count
767 | local file_input="$1" file_output="$2"
768 | while IFS= read -r line_input; do
769 | IFS="$old_IFS"
770 | line_output=""
771 | column_all_count="$(echo "$line_input" | awk '{ print NF }')"
772 | for ((column_count = 1; column_count <= column_all_count; column_count++)); do
773 | _filter_option_1_para -s --server
774 | _filter_option_1_para --custom-url --custom-url
775 | _filter_option_1_para -t --thread
776 | _filter_option_1_para --ping-mode --ping-mode
777 | _filter_option_0_para -m --multi
778 | _filter_option_0_para --no-download --no-download
779 | _filter_option_0_para --no-upload --no-upload
780 | done
781 | echo "$line_output" >>"$file_output"
782 | done <"$file_input"
783 | }
784 |
785 | # librespeed-cli
786 | _filter_option_librespeed_cli() {
787 | local line_input line_output column_count column_all_count
788 | local file_input="$1" file_output="$2"
789 | while IFS= read -r line_input; do
790 | IFS="$old_IFS"
791 | line_output=""
792 | column_all_count="$(echo "$line_input" | awk '{ print NF }')"
793 | for ((column_count = 1; column_count <= column_all_count; column_count++)); do
794 | _filter_option_1_para --server-json --server-json
795 | _filter_option_1_para --local-json --local-json
796 | _filter_option_1_para --server --server
797 | _filter_option_1_para --duration --duration
798 | _filter_option_0_para --no-download --no-download
799 | _filter_option_0_para --no-upload --no-upload
800 | _filter_option_0_para --no-icmp --no-icmp
801 | _filter_option_0_para -4 --ipv4
802 | _filter_option_0_para -6 --ipv6
803 | done
804 | echo "$line_output" >>"$file_output"
805 | done <"$file_input"
806 | }
807 |
808 | # iperf3
809 | _filter_option_iperf3() {
810 | local line_input line_output column_count column_all_count
811 | local file_input="$1" file_output="$2"
812 | while IFS= read -r line_input; do
813 | IFS="$old_IFS"
814 | line_output=""
815 | column_all_count="$(echo "$line_input" | awk '{ print NF }')"
816 | for ((column_count = 1; column_count <= column_all_count; column_count++)); do
817 | _filter_option_1_para -c -c
818 | _filter_option_1_para -P --parallel
819 | _filter_option_1_para -i --interval
820 | _filter_option_1_para -t --time
821 | _filter_option_1_para -O --omit
822 | _filter_option_0_para -R --reverse
823 | _filter_option_0_para -u --udp
824 | _filter_option_0_para -4 --version4
825 | _filter_option_0_para -6 --version6
826 | _filter_option_0_para --up-and-down --up-and-down
827 | _filter_option_iperf3_1 -p --port
828 | done
829 | echo "$line_output" >>"$file_output"
830 | done <"$file_input"
831 | }
832 |
833 | ########## 检测选项,用于预判测速结果 ##########
834 |
835 | _check_option() {
836 | local option_input="$1" options_input="$2"
837 | if echo "$options_input" | grep -q -- "$option_input"; then
838 | return 0
839 | else
840 | return 1
841 | fi
842 | }
843 |
844 | _check_num() {
845 | local num_input="$1"
846 | if [[ "$num_input" =~ ^[0-9]+(\.[0-9]+)?$ ]] && ! [[ "$num_input" =~ ^0+(\.0+)?$ ]]; then
847 | return 0
848 | else
849 | return 1
850 | fi
851 | }
852 |
853 | ########## 输出 ##########
854 |
855 | _check_output() {
856 | local i_check_output
857 | local count_check_output="0"
858 | for i_check_output in $(echo "$download $upload $latency $jitter"); do
859 | if [[ "$i_check_output" =~ 失败 ]]; then
860 | count_check_output=$((count_check_output + 1))
861 | elif [[ "$i_check_output" =~ 跳过 ]]; then
862 | count_check_output=$((count_check_output + 1))
863 | fi
864 | done
865 | [ "$count_check_output" -ne 4 ] && printf "${yellow}%-s${green}%-${download_c}s${cyan}%-${upload_c}s${blue}%-${latency_c}s${purple}%-${jitter_c}s${endc}\n" "$node_name" "$download" "$upload" "$latency" "$jitter"
866 | }
867 |
868 | ########## 删除残余文件 ##########
869 |
870 | _rm_dir() {
871 | _print_banner_4
872 | rm -rf "$work_dir"
873 | exit 0
874 | }
875 |
876 | ########## debug ##########
877 |
878 | _debug() {
879 | local debug_tar_name
880 | if [[ "$debug_flag" -eq 1 ]]; then
881 | {
882 | echo "OS info:"
883 | cat /etc/os-release
884 | echo "Shell info:"
885 | echo "$SHELL"
886 | echo "User info:"
887 | echo "$UID"
888 | echo "Loc info:"
889 | echo "$loc"
890 | } >$work_dir/info.txt
891 | debug_tar_name="sp-debug-$(TZ=Asia/Shanghai date +"%Y%m%d%H%M%S").tar"
892 | touch $work_dir/1.json
893 | tar -cf "$work_dir/$debug_tar_name" ${work_dir}/*.{json,txt}
894 | printf "\n${red}%-s${endc}\n" "方便的话欢迎将到GitHub反馈下述结果:"
895 | curl -X POST -s -Fc=@"$work_dir/$debug_tar_name" -Fn="${debug_tar_name%.*}" -Fe=90d 'https://pastebin.888853.xyz'
896 | echo
897 | fi
898 | }
899 |
900 | ########## main ##########
901 |
902 | _main() {
903 | trap '{ kill ${bar_pid} 2>/dev/null; printf "\r"; _debug; _rm_dir; }' EXIT
904 | _check_architecture
905 | _constant
906 | _print_banner_1
907 | _check_user
908 | _check_region
909 | _check_package tar tar
910 | _check_package curl curl
911 | _check_package iperf3 iperf3
912 | _check_package bc bc
913 | _make_dir
914 | _download_tar
915 | _check_tar_sha256
916 | _unzip_tar
917 | clear
918 | _get_node_list
919 | _classify_node
920 | clear
921 | _print_banner_1
922 | [ -s "$work_dir"/banner-custom.txt ] && _print_banner_2
923 | _print_banner_3
924 | [ -s "$work_dir"/speedtest-cli-node.txt ] && _speedtest_cli_test
925 | [ -s "$work_dir"/bim-core-node.txt ] && _bim_core_test
926 | [ -s "$work_dir"/speedtest-go-node.txt ] && _speedtest_go_test
927 | [ -s "$work_dir"/librespeed-cli-node.txt ] && _librespeed_cli_test
928 | [ -s "$work_dir"/iperf3-node.txt ] && _iperf3_test
929 | }
930 |
931 | ####################
932 |
933 | for arg in "$@"; do
934 | if [[ "$arg" == "--debug" ]]; then
935 | debug_flag="1"
936 | fi
937 | done
938 |
939 | _main
940 |
--------------------------------------------------------------------------------