Anonymous
Он не подходит мне
Alexander
Тогда покажи, что делает ssh.Scan
Anonymous
Да перезагрузка комп, повесил случайно
Anonymous
package ssh
import (
"fmt"
"net"
"time"
)
func Scan(thread int, jobs <-chan string, results chan<- string) {
for j := range jobs {
_, err := net.DialTimeout("tcp", j+":22", 5*time.Second)
if err != nil {
results <- fmt.Sprintf("Thread %d: %v\n", thread, err)
return
}
results <- fmt.Sprintf("Thread %d: %s port is opened.\n", thread, j)
}
}
Anonymous
Это вот сама функция scan
Alexander
https://play.golang.org/p/GmCueoKFXIj
Alexander
всё работает как надо
Anonymous
То есть этот код можно считать хорошим?
Anonymous
Просто вопрос был в том, что если у меня хостов например будет миллион, то я же не смогу позволить отработать миллион горутин
Alexander
Да, я сначала не понял, как именно работает ssh.Scan. Но так как он читает задачи из канала, то всё в целом правильно.
Alexander
Я бы только не стал делать канал с таким буфером - это бессмысленно
Michael
и беспощадно
Anonymous
Простой небуфиризированный сделать?
Chebyrash
Michael
но когда хочется и колится, то можно
Alexander
Да. Только читающую горутину запусти _сначала_
Anonymous
Почему нет?
Ну я пока не силен в го, вот и решил уточнить) По верному пути ли я иду
Anonymous
Chebyrash
Alexander
Можно много горутин 👌
Тут, я думаю, будут проблемы с сетью. Незачем сканировать сеть в миллион потоков.
Chebyrash
Anonymous
Alexander
Это правильно, да.
Chebyrash
Я думал у вас миллион коннектов
Anonymous
Всем спасибо, очень помогли) А то сижу со вчера и думаю как реализовать)
Michael
хорошо реализовывать надо) и про балансировку нагрузки на сеть не забывай
Anonymous
Anonymous
А так по честному, не очень у меня на го? Да?
Anonymous
Я просто до этого на питоне бацал
Michael
у всех не очень и все живут
Anonymous
)) Да вот только начал недавно) так в основном по вебу мелочевку всякую писал
Michael
у фастхттп были юзкейсы кмк
Michael
подходит для задач - используй
Michael
не подоходит - не используй
Anonymous
А wg на самом деле не очень подходит пока что, сейчас буду думать
Anonymous
Почитаю, посмотрим) Если интересно будет потом могу отписать, как решил это
Michael
запускаю нужное кол-во рутин, они слушают канал с тасками, когда канал закрываю, то и рутины завершаются
Michael
воркеры с манагером общаются аля Task & TaskResult сообщениями
Anonymous
Anonymous
и отслеживать одновременное кол-во запущенных, но не помню почему отмел эту идею
Michael
как наваяешь, лучше код покажи
Michael
кто нить да подскажет
Anonymous
Ну да, наверное так и сделаю, но пока проблем нет вроде
Alexander
WaitGroup (да, я ошибся, когда назвал их WorkerGroup) нужен чтобы не отслеживать количество результатов, а просто дождаться пока все горутины отработают. Вот пример - https://golang.org/pkg/sync/#example_WaitGroup
Anonymous
Это классическая задача решается или через семафоры или через thread pool. По крайней мере в оствльных языках
Anonymous
Alexander
Если сделаешь чтение или запись в отдельной горутине, как я рекомендовал выше (чтобы буфер в канале не делать равным количеству данных), то ожидание завершения работы горутин станет актуальным.
Anonymous
Alexander
Вот с записью в отдельной горутине и канал без буфера - https://play.golang.org/p/E725utf5Et_X
Alexander
Можно сделать наоборот - считывать в отдельной горутине, а записывать в основном потоке
Alexander
Главное - чтобы и запись и чтение работали одновременно
Anonymous
Хм
Anonymous
Ща попробую
Anonymous
Погоди, а вот ожидание завершения у меня происходит же по сути по освобождению данных из канала, то есть то что я сделал запись в отдельной горутине, мало что поменяло вроде, единственное, что к ней нужен будет waitgroup
Anonymous
Или я ошибаюсь?
Anonymous
Ну то есть пока я не освобожу канал полностью, горутина не перестанет работать
Anonymous
Так же?
Anonymous
Я может быть не так что - то понимаю
Michael
в мейне создаю несколько воркеров
Alexander
WaitGroup тут пока не нужен, т.к. всё еще есть подсчет задач. А смысл изменения - убрать буфер у канала и сохранить немного памяти (ну или много)
Michael
а... оптимизируете)
Anonymous
А, понял. Просто еще с объемами данных такими не успел столкнуться, надо бы попробовать поигратьсья с огромным кол-вом данных
Michael
для моих задач работает такой вариант
создаём два канала - один для таском, другой для done сообщений или результатов
поднимается нужно кол-во горутин
при завершении канал с тасками закрывает
начинаем вычитывать done сообщения (тут есть блокировка осн потока выполнения)
как все отчитались, так и завершаем выполнение
Alexander
Michael
Michael
Alexander
да
Ну так тоже можно, да. Только WaitGroup же сделан именно для этого.
Michael
Anonymous
Anonymous
Я вот как переделал сейчас
Anonymous
package main
import (
"flag"
"fmt"
"log"
"sync"
"x/ssh"
)
func main() {
var wg sync.WaitGroup
pool := flag.String("p", "", "IP format 192.168.1.0/24")
flag.Parse()
// 64.254.32.0/24
hosts, err := ssh.GenerateHosts(*pool)
if err != nil {
log.Fatalf("[ERROR] %v\n", err)
}
results := make(chan string, 5)
for _, host := range hosts {
wg.Add(1)
go func(host string) {
wg.Done()
ssh.Scan(host, results)
}(host)
}
wg.Wait()
for i := 0; i < len(hosts); i++ {
fmt.Print(<-results)
}
}
Anonymous
jobs убрал за ненадобностью
Michael
а чего результаты аж на 5?
Anonymous
А да это еще не трогал)
Anonymous
я вот кстати не до конца еще буффер понимаю у канадов
Michael
wg.Done()
ssh.Scan(host, results)
done после Scan?
Anonymous
ой