LINUX.ORG.RU

Скрипт для загрузки файлов через scp

 ,


0

1

Я вообще не очень в теме, как стоило решить подобную задачу, но ко мне пришло такое решение и я хочу поделиться им с комьюнити, и, надеюсь, на адекватную критику и всё такое. Суть задачи - нужно загружать из определённой директории (директорий) файлы через scp, если директории нет - создать её. По мере развития проекта файлов и директорий становится много, потому нужно проверять, во-первых, не создана ли ещё директория (чтобы лишний раз не дёргать сервер), во-вторых, был ли изменён файл (чтобы лишний раз не гонять его по сети). Для хранения данных используются два файла: для информации о загруженных файлах и о созданных директориях. Собственно, вот код на третьем питоне. Язык я знаю крайне паршиво, так что, вероятно, можно было написать всё покороче... но зато вроде всё работает.

# -*- coding: utf-8 -*-
import os
from pathlib import Path
import paramiko
from paramiko import SSHClient
from scp import SCPClient

SERVER_IP = "192.168.0.1"
SERVER_USERNAME = "root"
SERVER_PASSWORD = "toor"
SERVER_DIRECTORY = '/var/www/html'
CACHE_FILES = "uploader-cache-files.txt"
CACHE_DIRS = "uploader-cache-dirs.txt"

def check_file_changes(name: str) -> bool:
	my_file = Path(CACHE_FILES)

	if not my_file.is_file():
		f = open(CACHE_FILES, "w+")
		f.close()

	f = open(CACHE_FILES, "r")
	lines = []

	while True:
		line = f.readline()

		if not line:
			f.close()
			break

		lines.append(line)

	need_load = False
	found = False

	f = open(CACHE_FILES, "w")
	for line in lines:
		pair = line.split('|')
		file_name = pair[0]
		file_size = int(pair[1])
		statinfo = os.stat(file_name)

		if file_name == name:
			found = True

			if statinfo.st_size != file_size:
				line = file_name + '|' + str(statinfo.st_size) + '\r\n'
				need_load = True

		f.write(line)

	if not found:
		need_load = True
		statinfo = os.stat(name)
		line = name + '|' + str(statinfo.st_size) + '\r\n'
		f.write(line)

	f.close()

	return need_load

def need_create_dir(name: str) -> bool:
	my_file = Path(CACHE_DIRS)

	if not my_file.is_file():
		f = open(CACHE_DIRS, "w+")
		f.close()

	f = open(CACHE_DIRS, "r")
	lines = []

	while True:
		line = f.readline()

		if not line:
			f.close()
			break

		lines.append(line)

	found = False
	f = open(CACHE_DIRS, "w")
	for line in lines:
		if line.strip() == name:
			found = True

		f.write(line.strip() + '\r\n')

	if not found:
		f.write(name + '\r\n')

	return not found

def need_upload_file(name: str) -> bool:
	if name == '.htaccess':
		return True

	ext = name.split('.')
	ext = ext[len(ext) - 1]

	if ext in ['php', 'css', 'js', 'png', 'jpg', 'gif', 'sql']:
		return True

	return False

def upload_file(name: str, path: str, scp: SCPClient):
	if check_file_changes(name):
		print("File '" + name + "' uploading...")
		scp.put(name, path)
	else:
		print("File '" + name + "' skip")

def upload_directory(name: str, ssh: SSHClient, scp: SCPClient):
	print("Observe '" + name + "' directory...")

	if name != '.' and need_create_dir(name):
		ssh.exec_command('mkdir -p ' + SERVER_DIRECTORY + '/' + name)

	files = [f for f in os.listdir(name) if os.path.isfile(name + '/' + f)]
	for f in files:
		if need_upload_file(f):
			upload_file(name + '/' + f, SERVER_DIRECTORY + '/' + name, scp)

	dirs = [d for d in os.listdir(name) if os.path.isdir(name + '/' + d)]
	for d in dirs:
		if d not in ['.', '..', '.git', '__pycache__']:
			upload_directory(name + '/' + d, ssh, scp)

def upload():
	ssh = SSHClient()
	ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
	ssh.connect(SERVER_IP, 22, SERVER_USERNAME, SERVER_PASSWORD)
	scp = SCPClient(ssh.get_transport())
	upload_directory('app', ssh, scp)
	scp.close()
	ssh.close()

if __name__ == "__main__":
	upload()

Я конечно извиняюсь, но зачем всё это, когда есть rsync?

Т.е. что-то вроде:

rsync -zavP /var/www/html remoteuser@X.X.X.X:/var/www/html
И всё, rsync сам создать недостающие директории, если они уже есть, то он обновит только те файлы, которые изменились.

anonymous ()

Когда хочется написать какую-то консольную дичь, вспоминай, что юниксу почти полтос, всё уже давно написано и в худшем случае потребуется несколько строк на баше.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Когда хочется написать какую-то консольную дичь, вспоминай, что юниксу почти полтос, всё уже давно написано и в худшем случае потребуется несколько строк на баше.

ТС, прислушайся к этому регистранту, он очень мудр, как я, и очень быстр, как понос.

И rsync я тоже умножаю.

mord0d ★★★★★ ()
Ответ на: комментарий от MetalBeaver

В мане, в который тебя послали, про это есть.

d_a ★★★★★ ()
Ответ на: комментарий от MetalBeaver

Если ты не в курсе, то при такой форме записи rsync как раз и работает через ssh.

Вот эта запись username@host:/var/www/html и указывает, что нужно подкчиться на сервер host под пользователем username и прогнать через scp, который работает поверх ssh файлы.

Сходи уже в man rsync и почитай как он работает.

Только на хосте источнике и хосте приёмнике нужно установить пакет rsync.

Почитай пожалуйста уже что-нибудь по rsync, хотя бы man, а не пиши свои мысли без прочтения документации.

Удачи.

anonymous ()
Ответ на: комментарий от MetalBeaver

Мне он не нужен и не интересен, есть rsync, в котором есть весь нужный функционал и даже больше, чем предоставляет твой скрипт.

Так что если тебе нужен велосипед - используй. Я же предпочту использовать проверенное решение, rsync.

anonymous ()
Ответ на: комментарий от MetalBeaver

Где ты видишь озлобленность?

Я понмаю, что ты старался, писал что-то. Но тебе абсолютно по доброму сказали, что то, что ты написал - велосипед, т.к. есть проверенное годами рабочее решение, rsync. О котором ты не знал.

Тебе сказали почитать по нему документацию в первом же сообщении в теме. Но ты этого не сделал, потому как опять настаивал, что доступен только ssh, делаем вывод то, что тебе написали ты проигнорировал. В то же время в документции по rsync ясно всё написано и понятно что он как раз и работает через ssh (scp) и как бы делает как раз то, что тебе нужно. К тому же делает 100% верно, плюс может ещё сжимать трафик.

Из всего этого можно сделать вывод: никому кроме тебя твой самописный велосипед не нужен, т.к. все кому нужен описанный твой функциона используют rsync - это стандарт.

Поэтому разбираться в твоём коде никто не будет, никому он не нужен.

Поэтому, если ты считаешь, что если дали совет и указали на уже готовое провернное решение, вместо того, что ты написал велосипед, невежливастью, то извини ты сам невежлив. Ибо во-первых, ты игнорируешь разумные советы тебе, теюя учат что есть уже готовое решение, во-вторых, требуешь что бы в никому не нужном коде кроме разобрались, он никому не нужен, в третьих говоришь, что здесь все невежливы и озлоблены. Извини, но елси ты не понимаешь что данное тебе указание на rsync - это не озлобленность, а помощь тебе и обучение, то что тебе ещё сказать я не знаю.

anonymous ()
Ответ на: комментарий от MetalBeaver

А по коду есть что сказать?

Код говно. Где --help? Что за хардкод с 22 портом, именами файлов и хостом/юзером/паролем в скрипте? Постыдился бы.

'\r\n'
А это что еще за недоразумение? Ты потроллить хотел?

crutch_master ★★★★★ ()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от WitcherGeralt

Когда хочется написать какую-то консольную дичь, вспоминай, что юниксу почти полтос, всё уже давно написано и в худшем случае потребуется несколько строк на баше.

Ну если всё написано, то, наверное, уже и коммунизм настал. А новые языки так вообще не нужны, когда есть божественная сишечка. Или может таки стоит иногда пытаться что-то писать новое на новом? А то получается с одной стороны - практика разработки сводится к жонглированию паттернами и готовыми фреймфорками, а база наработанная российскими девелоперами - примерно к нулю.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

Т.е. ты уверен, что твой код выполняемый интерпретатором python будет работать быстрее кода на СИ скомпилированного в бинарный формат?

К тому же он делает вообще не понятно что и зачем, когда есть rsync уже проверенный годами, десятилетиями.

Так что объясни тогда зачем он вообще нужен?

anonymous ()
Ответ на: комментарий от anonymous

Т.е. ты уверен, что твой код выполняемый интерпретатором python будет работать быстрее кода на СИ скомпилированного в бинарный формат?

Значит питон вообще не нужен выходит. Ведь всё можно написать на сишечке. А что не на сишечке - то на Go/Rust.

К тому же он делает вообще не понятно что и зачем, когда есть rsync уже проверенный годами, десятилетиями.
Так что объясни тогда зачем он вообще нужен?

Насколько я понял, rsync нужно ставить и на сервере? У меня есть доступ по ssh для залива файлов, создания директорий в определённой резервации. Мне нужно заливать с компьютера файлы, которые а) были обновлены б) имеют определённые расширения в) из определённых директорий.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

Значит питон вообще не нужен выходит. Ведь всё можно написать на сишечке. А что не на сишечке - то на Go/Rust.

С демагогией ты не на тот ресурс пришёл, ну, как и за аудитом своего кода.

vvn_black ★★★★★ ()
Ответ на: комментарий от MetalBeaver

Язык я знаю крайне паршиво

Код, наверное, получше чем «паршиво», но это не стиль «современного» питона.

Почему русское комьюнити такое озлобленное?

Какое не русское не озлобленное?

vvn_black ★★★★★ ()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Какое не русское не озобленное?

С демагогией ты не на тот ресурс пришёл.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

А что не так с этим ресурсом?

В первую очередь что-то не так с тобой.

vvn_black ★★★★★ ()
Ответ на: комментарий от MetalBeaver

Значит питон вообще не нужен выходит. Ведь всё можно написать на сишечке. А что не на сишечке - то на Go/Rust.

Ну я надеюсь ты понимаешь, что код на скриптовом языке, который не компилируется, а выполняется интерпретатором работает медленнее кода, который написан на компилируемом языке и из которого получаются бинарники.

Мне нужно заливать с компьютера файлы, которые а) были обновлены б) имеют определённые расширения в) из определённых директорий.

Файлы которые были обновлены проверит rsync, расширения указываются смотри ниже я написал, определённые директории указываются в параметрах rsync.

Если откроешь man rsync и почитаешь хотя бы его, то увидишь, что у rsync есть параметры:

     --exclude=PATTERN       exclude files matching PATTERN
     --exclude-from=FILE     read exclude patterns from FILE
     --include=PATTERN       don't exclude files matching PATTERN
     --include-from=FILE     read include patterns from FILE
с помощью этих параметров можно указать типы файлов, которые тебе нужно синхронизировать, можно указать в отдельном файле на каждой строчке один формат, т.е. что-то вроде:
*.php
*.css
*.js
*.png
*.jpg
*.gif
*.sql

Если говорить о твоей задаче, то есть уже готовый инструмент, который проверен годами и 100% работает. Поэтому, ты можешь использовать свой велосипед - вперёд, никто не запрещает. Но он никому кроме тебя не нужен, т.к. есть уже готовый, универсальный инструмент, rsync.

Насколько я понял, rsync нужно ставить и на сервере?

Да, rsync должен быть установлен на системе источнике и приёмнике.

Т.е. тебе нужно всего навсего набрать команду установки rsync на сервере и всё.

anonymous ()

Беда современного СПО в том...

...что 99% его пишется не для решить проблему, а для привлечь к себе внимание.

anonymous ()
Ответ на: комментарий от MetalBeaver

Вот только ты написал этот велосипед из простого невежества, иначе бы не запилил этот пост. Не говоря уже о том, что оно даже близко не сравнимо по функциональности с rsync и код — говнище (научить в контекст-менеджеры хотя бы).

Велосипеды писать нормально, только не надо ходить на лор и тут свою дрянь выставлять, если надеешься на другую реакцию.

WitcherGeralt ★★ ()
Ответ на: комментарий от vzzo

Просто у него нет Code of Conduct правильного.

Ну в реале за дерзость у нас принято давать в рыло, а в виртуале - хамить друг другу кто во что горазд. Не первое десятилетие я в Сети - ничего не меняется.

MetalBeaver ()
Ответ на: комментарий от WitcherGeralt

контекст-менеджер

Что это такое?

и тут свою дрянь выставлять

Я надеялся на адекватную критику. Спасибо большое, что рассказали про rsync, - я не знал о его существовании и о том, что он может решить мою задачу проще и быстрее. Но также, я был бы признателен, если бы мне указали, почему мой код - дрянь... Я сразу сказал, что питон знаю плохо, надеялся, что комьюнити подскажет, что можно поправить, чтобы было более кошерно.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

Фифа какая, ему сказали, что его код плох и тем более, что это велосипед, потому как есть rsync, выполняющий поставленную задачу.

Да ты сам дерзишь, вместо того, что бы сказать сразу же: «Спасибо, что направили по правильному пути» и прочитать ман страницу по rsync указываешь сообществу что оно ему дерзит и не хочет разбираться в твоём велосипеде и признавать твои «достижения».

Тебе самому первому в рыло дать нужно.

anonymous ()
Ответ на: комментарий от MetalBeaver

что питон знаю плохо, надеялся, что комьюнити подскажет, что можно поправить, чтобы было более кошерно.

Я тебе сказал, что поправить, ты поправил?

crutch_master ★★★★★ ()
Ответ на: комментарий от MetalBeaver

Что это такое?

На случай если ещё не осилил погуглить, то вот: https://www.python.org/dev/peps/pep-0343/

Если тебе действительно нужна непосредственная критика кода, то юзай os.path и форматирование (C-style, . format, f-strings — любой удобный вариант, но только один) вместо конкатенации. Ну и argparser.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от MetalBeaver

А новые языки так вообще не нужны, когда есть божественная сишечка.

У божественной сишечки есть серьёзные и известные недостатки, которые мешают писать на ней прикладное ПО, поэтому ей периодически пытаются найти заменители. Иногда это получается.

У rsync недостатки наверняка есть, так почему бы тебе их не найти ДО того, как собирать свой велосипед? И ещё стоит подумать, заслуживают ли они написания нового продукта с нуля, или имеет смысл просто пропатчить rsync?

Или может таки стоит иногда пытаться что-то писать новое на новом?

Если для того, чтобы это новое было лучше старого — стоит. Если только для того, чтобы оно было новым — это клиника.

а база наработанная российскими девелоперами - примерно к нулю

А это самоцель? Российские «девелоперы», внёсшие свой вклад в СПО, есть, и некоторые из них даже присутствуют на ЛОРе. Но думаю, они писали не для того, «чтобы было», а чтобы решить вполне конкретные проблемы.

P.S. Я тебя не отговариваю от того, чтобы ты писал что-то своё, а всего лишь предлагаю оптимизировать усилия. Может, тебя ждёт задача, которую, в отличие от синхронизации по SSH, ещё никто не решил?

hobbit ★★★★★ ()
Последнее исправление: hobbit (всего исправлений: 1)
2 декабря 2018 г.
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.