mirror of
https://github.com/seqizz/go-tools.git
synced 2024-09-12 21:30:12 +02:00
initial
This commit is contained in:
commit
c887b307eb
6 changed files with 775 additions and 0 deletions
201
LICENSE
Normal file
201
LICENSE
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
10
README.md
Normal file
10
README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# go-tools
|
||||
Collection of tools I've written in golang
|
||||
|
||||
- **did**: A simple, cli-based task logger. Mainly intended for multi-admin environments.
|
||||
|
||||
- **kahin**: A tool to find which directory fills the given disk, with a somewhat unique algorithm.
|
||||
|
||||
- **mprun**: Miserable parallel script runner
|
||||
|
||||
- **wwn**: Shows FC wwn's of a Linux system
|
160
did/did.go
Normal file
160
did/did.go
Normal file
|
@ -0,0 +1,160 @@
|
|||
package main
|
||||
|
||||
// gurkan.in | license: Apache License 2.0 shared on https://github.com/seqizz/go-tools/blob/master/LICENSE
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"database/sql"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rmFlag := flag.Int("rm", 0, "Remove the specified entry")
|
||||
editFlag := flag.String("edit", "", "Edit the specified entry: 3:NewValue")
|
||||
showFlag := flag.Bool("show", false, "Show the current done list")
|
||||
flag.Parse()
|
||||
|
||||
//can't believe I need this for portability
|
||||
findHome, err := homedir.Dir()
|
||||
errCheck(err)
|
||||
|
||||
db, err := sql.Open("sqlite3", findHome+"/.did.db")
|
||||
errCheck(err)
|
||||
defer db.Close()
|
||||
|
||||
sqlStmt := `
|
||||
create table if not exists didtable (id integer primary key autoincrement, date string not null, did string not null);
|
||||
`
|
||||
_, err = db.Exec(sqlStmt)
|
||||
if err != nil {
|
||||
log.Printf("%q: %s\n", err, sqlStmt)
|
||||
return
|
||||
}
|
||||
tx, err := db.Begin()
|
||||
errCheck(err)
|
||||
|
||||
//if only show is specified, show the contents and exit
|
||||
if strings.Join(os.Args[1:], "@") == "show" {
|
||||
*showFlag = true
|
||||
}
|
||||
|
||||
if *showFlag {
|
||||
showAllValues(tx)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *rmFlag == 0 {
|
||||
if len(*editFlag) == 0 {
|
||||
//not editing nor removing, so let's add
|
||||
if len(os.Args) > 1 {
|
||||
addValue(strings.Join(os.Args[1:], " "), tx)
|
||||
} else {
|
||||
infoText()
|
||||
}
|
||||
} else {
|
||||
//editFlag
|
||||
mid := strings.Split(strings.Join(os.Args[2:], " "), ":")
|
||||
if len(mid) == 2 {
|
||||
myid, err := strconv.Atoi(mid[0])
|
||||
errCheck(err)
|
||||
changeValue(myid, mid[1], tx)
|
||||
} else {
|
||||
fmt.Println("Please use the format id:text (Example: -edit 3:updated the script)")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//rmFlag
|
||||
rmValue(*rmFlag, tx)
|
||||
fmt.Println("Removed", *rmFlag)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func errCheck(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func addValue(what string, tx *sql.Tx) bool {
|
||||
stmt, err := tx.Prepare("insert into didtable(date, did) values(?, ?)")
|
||||
errCheck(err)
|
||||
const layout = "02 Jan 2006 15:04"
|
||||
_, err = stmt.Exec(time.Now().Format(layout), what)
|
||||
errCheck(err)
|
||||
stmt.Close()
|
||||
tx.Commit()
|
||||
return true
|
||||
}
|
||||
|
||||
func changeValue(id int, what string, tx *sql.Tx) bool {
|
||||
stmt, err := tx.Prepare("update didtable set did = ? where id = ?")
|
||||
errCheck(err)
|
||||
_, err = stmt.Exec(what, id)
|
||||
errCheck(err)
|
||||
stmt.Close()
|
||||
tx.Commit()
|
||||
return true
|
||||
}
|
||||
|
||||
func rmValue(id int, tx *sql.Tx) bool {
|
||||
stmt, err := tx.Prepare("delete from didtable where id=?")
|
||||
errCheck(err)
|
||||
_, err = stmt.Exec(id)
|
||||
errCheck(err)
|
||||
stmt.Close()
|
||||
tx.Commit()
|
||||
return true
|
||||
}
|
||||
|
||||
func showAllValues(tx *sql.Tx) bool {
|
||||
results, err := tx.Query("select * from didtable")
|
||||
errCheck(err)
|
||||
defer results.Close()
|
||||
tx.Commit()
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"ID", "Date", "What"})
|
||||
table.SetCenterSeparator(" ")
|
||||
table.SetColumnSeparator(" ")
|
||||
table.SetRowLine(false)
|
||||
|
||||
for results.Next() {
|
||||
var id int
|
||||
var date string
|
||||
var what string
|
||||
err = results.Scan(&id, &date, &what)
|
||||
errCheck(err)
|
||||
mid := []string{strconv.Itoa(id), date, what}
|
||||
table.Append(mid)
|
||||
}
|
||||
table.Render()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func infoText() {
|
||||
fmt.Println(`
|
||||
This program is intended to keep a basic version of what happened on the server on multi-admin environments.
|
||||
|
||||
Usage:
|
||||
|
||||
did installed python
|
||||
did upgraded glibc
|
||||
did -show
|
||||
did -rm 2
|
||||
did -update 1:installed python 2.7
|
||||
`)
|
||||
}
|
174
kahin/kahin.go
Normal file
174
kahin/kahin.go
Normal file
|
@ -0,0 +1,174 @@
|
|||
package main
|
||||
|
||||
// gurkan.in | license: Apache License 2.0 shared on https://github.com/seqizz/go-tools/blob/master/LICENSE
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/labstack/gommon/bytes"
|
||||
)
|
||||
|
||||
var baseLevel, curLevel, count int
|
||||
var treshold, biggest, tmpGuiltySize int64
|
||||
var champ, tmpGuilty string
|
||||
var guilty []string
|
||||
var guiltySize []int64
|
||||
|
||||
func main() {
|
||||
cmdName := "du"
|
||||
|
||||
var cmdArgs []string
|
||||
allInOne := make(map[string]int64)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if len(os.Args) == 1 || len(os.Args) > 3 {
|
||||
usage()
|
||||
}
|
||||
|
||||
if _, err := os.Stat(os.Args[1]); os.IsNotExist(err) {
|
||||
fmt.Fprintln(os.Stderr, "Couldn't find:", os.Args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
rootFolder := os.Args[1]
|
||||
|
||||
baseLevel = strings.Count(rootFolder, "/")
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
cmdArgs = []string{"-x", rootFolder}
|
||||
} else if runtime.GOOS == "solaris" {
|
||||
cmdArgs = []string{"-d", rootFolder}
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdName, cmdArgs...)
|
||||
cmdReader, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
scanner := bufio.NewScanner(cmdReader)
|
||||
|
||||
go runCommand(scanner, allInOne, &wg)
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error starting Cmd", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
isDone := false
|
||||
|
||||
curLevel = baseLevel + 1
|
||||
|
||||
treshold = 30
|
||||
|
||||
if len(os.Args) == 3 {
|
||||
count, err = strconv.Atoi(os.Args[2])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
count = 3
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
guiltySize[i], guilty[i] = calculate(allInOne, curLevel, isDone, i)
|
||||
s := bytes.Format(guiltySize[i] * 1024)
|
||||
|
||||
fmt.Println(guilty[i], s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprint(os.Stdout, "\nKahin finds the most revelant space-hugger directories under given path\n(and does not calculate other mountpoints found).\n\nUsage:\n\tkahin {directory} {count}\n\nFor example, if you want to find 5 most revelant directories, use:\n\n\tkahin /data 5\n\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func runCommand(scanner *bufio.Scanner, allInOne map[string]int64, wg *sync.WaitGroup) {
|
||||
for scanner.Scan() {
|
||||
splitted := strings.Split(scanner.Text(), "\t")
|
||||
myint, err := strconv.ParseInt(splitted[0], 10, 64)
|
||||
if err == nil {
|
||||
allInOne[splitted[1]] = myint
|
||||
}
|
||||
// fmt.Printf("command output | %s\n", scanner.Text())
|
||||
// fmt.Printf("checking if map is ok | %d\n", allInOne[splitted[1]])
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func levelCount(str string) int {
|
||||
level := strings.Count(str, "/")
|
||||
return level
|
||||
}
|
||||
|
||||
func calculate(myMap map[string]int64, curLevel int, isDone bool, number int) (int64, string) {
|
||||
if isDone {
|
||||
guilty = append(guilty, tmpGuilty)
|
||||
guiltySize = append(guiltySize, tmpGuiltySize)
|
||||
tmpGuilty = ""
|
||||
tmpGuiltySize = 0
|
||||
treshold = 30
|
||||
curLevel = baseLevel + 1
|
||||
return guiltySize[number], guilty[number]
|
||||
}
|
||||
|
||||
biggest = 0
|
||||
champ = ""
|
||||
tempMap := make(map[string]int64)
|
||||
|
||||
for k, v := range myMap {
|
||||
if levelCount(k) == curLevel {
|
||||
if !isSliceContainsRgx(guilty, k) {
|
||||
tempMap[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range tempMap {
|
||||
if v > biggest {
|
||||
biggest = v
|
||||
champ = k
|
||||
}
|
||||
}
|
||||
if biggest > tmpGuiltySize/100*treshold {
|
||||
tmpGuiltySize = biggest
|
||||
tmpGuilty = champ
|
||||
curLevel++
|
||||
treshold = treshold + 10
|
||||
} else {
|
||||
isDone = true
|
||||
}
|
||||
|
||||
return calculate(myMap, curLevel, isDone, number)
|
||||
}
|
||||
|
||||
func isSliceContainsRgx(slice []string, text string) bool {
|
||||
for _, a := range slice {
|
||||
a = strings.Replace(a, "(", "\\(", -1)
|
||||
a = strings.Replace(a, ")", "\\)", -1
|
||||
a = strings.Replace(a, "[", "\\[", -1)
|
||||
a = strings.Replace(a, "]", "\\]", -1)
|
||||
matched, _ := regexp.MatchString(a+".*", text)
|
||||
matchedReverse, _ := regexp.MatchString(text, a+".*")
|
||||
if matched || matchedReverse {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
151
mprun/mprun.go
Normal file
151
mprun/mprun.go
Normal file
|
@ -0,0 +1,151 @@
|
|||
package main
|
||||
|
||||
// gurkan.in | license: Apache License 2.0 shared on https://github.com/seqizz/go-tools/blob/master/LICENSE
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
// "time"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/cheggaaa/pb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
lineFlag := flag.String("inputfile", "inputfile.input", "File to read inputs")
|
||||
commandFlag := flag.String("script", "my.script", "File to run")
|
||||
runnerFlag := flag.String("runner", "bash", "Script interpreter")
|
||||
outputFlag := flag.String("output", "results.txt", "Result file")
|
||||
workerFlag := flag.Int("workers", 2, "Worker thread count")
|
||||
verboseFlag := flag.Bool("verbose", false, "Print output to stdout")
|
||||
flag.Parse()
|
||||
|
||||
if (len(os.Args) < 2) || (strings.Contains(os.Args[1], "-help")) {
|
||||
howto()
|
||||
}
|
||||
|
||||
if _, err := os.Stat(*lineFlag); os.IsNotExist(err) {
|
||||
fmt.Fprintln(os.Stderr, "Couldn't find inputfile:", *lineFlag)
|
||||
os.Exit(1)
|
||||
}
|
||||
if _, err := os.Stat(*commandFlag); os.IsNotExist(err) {
|
||||
fmt.Fprintln(os.Stderr, "Couldn't find script:", *commandFlag)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lines, err := readLines(*lineFlag)
|
||||
errcontrol(err)
|
||||
bar := pb.New(len(lines))
|
||||
bar.ShowTimeLeft = false
|
||||
bar.ShowSpeed = false
|
||||
|
||||
f, err := os.OpenFile(*outputFlag, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||
errcontrol(err)
|
||||
defer defClose(f)
|
||||
|
||||
// _ = "breakpoint"
|
||||
|
||||
c := make(chan string, *workerFlag)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(*workerFlag)
|
||||
for i := 0; i < *workerFlag; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if !*verboseFlag {
|
||||
Process(c, *commandFlag, f, *runnerFlag, *verboseFlag, bar)
|
||||
} else {
|
||||
Process(c, *commandFlag, f, *runnerFlag, *verboseFlag, nil)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, hostname := range lines {
|
||||
c <- hostname
|
||||
}
|
||||
|
||||
close(c)
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// Process : Actual working process for one thread
|
||||
func Process(c chan string, command string, file *os.File, interpreter string, isVerbose bool, progBar *pb.ProgressBar) {
|
||||
for hostname := range c {
|
||||
var out bytes.Buffer
|
||||
// time.Sleep(time.Millisecond * 1000)
|
||||
if !isVerbose {
|
||||
progBar.Start()
|
||||
progBar.Increment()
|
||||
} else {
|
||||
fmt.Printf("Processing: %s\n", hostname)
|
||||
}
|
||||
cmd := exec.Command(interpreter, command, hostname)
|
||||
cmd.Stdout = &out
|
||||
err := cmd.Run()
|
||||
errcontrol(err)
|
||||
_, writeErr := file.WriteString(out.String() + "\n")
|
||||
errcontrol(writeErr)
|
||||
|
||||
if isVerbose {
|
||||
fmt.Fprintln(os.Stdout, out.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readLines(path string) ([]string, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer defClose(file)
|
||||
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
return lines, scanner.Err()
|
||||
|
||||
}
|
||||
|
||||
func howto() {
|
||||
fmt.Println(`
|
||||
Welcome to the Miserable Parallel Runner
|
||||
|
||||
This program runs given script in multiple threads, and feeds every one of them a line from a text file.
|
||||
|
||||
Example:
|
||||
./mprun -workers=3 -inputfile=myhostfile -script=myscript.py -runner=python3 -output=results.csv -verbose
|
||||
|
||||
This will run myscript.py n times (n = line count of "myhostfile")
|
||||
|
||||
|
||||
workers: Worker thread count to run parallel
|
||||
inputfile: File (hostnames/IP addresses etc.) to feed into script
|
||||
script: Main file to run
|
||||
runner: Interpreter for 'script' (python2, python3, bash etc.)
|
||||
output: File to write results in
|
||||
verbose: Prints script's output to both file and stdout
|
||||
`)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func defClose(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stdout, "Failed to close file")
|
||||
}
|
||||
}
|
||||
|
||||
func errcontrol(e error) {
|
||||
if e != nil {
|
||||
fmt.Fprintln(os.Stderr, e)
|
||||
}
|
||||
}
|
79
wwn/wwn.go
Normal file
79
wwn/wwn.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package main
|
||||
|
||||
// gurkan.in | license: Apache License 2.0 shared on https://github.com/seqizz/go-tools/blob/master/LICENSE
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"fmt"
|
||||
"strings"
|
||||
"os"
|
||||
"bufio"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"flag"
|
||||
)
|
||||
|
||||
func main(){
|
||||
|
||||
fcdir := "/sys/class/fc_host/"
|
||||
|
||||
outputFlag := flag.String("output", "table", "Output style: table or plain")
|
||||
stateFlag := flag.String("state", "all", "State filter: online, offline or all")
|
||||
flag.Parse()
|
||||
|
||||
files, err := ioutil.ReadDir(fcdir)
|
||||
if err != nil {
|
||||
fmt.Println("Couldn't find any FC interfaces")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
if *outputFlag == "table" {
|
||||
table.SetHeader([]string{"Name", "State", "Current Speed", "Supported Speeds", "WWN"})
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
state, _ := readLines(fcdir + file.Name()+ "/port_state")
|
||||
speed, _ := readLines(fcdir + file.Name()+ "/speed")
|
||||
suppspeed, _ := readLines(fcdir + file.Name()+ "/supported_speeds")
|
||||
wwn, _ := readLines(fcdir + file.Name()+ "/port_name")
|
||||
mid := []string{file.Name(), state[0], speed[0], suppspeed[0], wwn[0]}
|
||||
|
||||
if *outputFlag == "table" {
|
||||
if *stateFlag == "all" {
|
||||
table.Append(mid)
|
||||
} else if ( *stateFlag == "online" && state[0] == "Online" ) {
|
||||
table.Append(mid)
|
||||
} else if ( *stateFlag == "offline" && state[0] == "Linkdown") {
|
||||
table.Append(mid)
|
||||
}
|
||||
} else if *outputFlag == "plain" {
|
||||
pln := strings.Join(mid, ";")
|
||||
if *stateFlag == "all" {
|
||||
fmt.Fprintln(os.Stdout, pln)
|
||||
} else if ( *stateFlag == "online" && state[0] == "Online" ) {
|
||||
fmt.Fprintln(os.Stdout, pln)
|
||||
} else if ( *stateFlag == "offline" && state[0] == "Linkdown") {
|
||||
fmt.Fprintln(os.Stdout, pln)
|
||||
}
|
||||
}
|
||||
}
|
||||
if *outputFlag == "table" {
|
||||
table.Render()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func readLines(path string) ([]string, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
return lines, scanner.Err()
|
||||
}
|
Loading…
Reference in a new issue