вам подстать написать на хабре.
У меня плохо с написанием =)
========================
И снова здравствуйте.
В этой главе я опишу один маленький компонент и так же часть довольно большой подсистемы.
И так. Маленький компонент FrClientOS, в который я изначально хотел собрать всякие вызовы работы с операционной системой, но получился пока только один вызов. Вызов execute принимает в качестве параметра строку и исполняет на стороне агента шелл с этой командой. Короче делает банальный вызов system со всеми его плюсами и минусами.
Плюс в том, что он довольно простой для реализации и использует шелл юзера под которым будет исполнен (в случае виртурилки это рутовый bash)
Минус в том, что он довольно долгий и если агент занят исполнением этого вызова, то этот вызов занимает один из потоков-исполнителей. Это значит, что если эти потоки исполнители будут заняты все, то клиент уже не сможет ничего исполнить, не дождавшись завершения system, Поэтому нужно аккуратно эту штуку использовать.
Компонент QML
Как писал выше, называется он FrClientOS и требует только основного для всех компонентов свойства - client, которым он связан с соединенным клиентом. Выглядит все это очень просто:
- Код: Выделить всё
Item {
FrClientOS {
id: shellExecutor /// id по которому будет идентифицирован внутри скрипта
client: remoteClient
}
}
Item на самом деле не обязателен, но, по традиции из прошлых постов, сделаю его тоже отдельным айтемом.
Далее план просто: Сделать поле ввода, сделать кнопку и по нажатию этой кнопки сделать shellExecutor.execute(cmd).
Получилось что-то типа такого:
- Код: Выделить всё
Item {
FrClientOS {
id: shellExecutor
client: remoteClient
}
Connections { /// ракция на нажатие кнопки runButton
target: runButton
onClicked: shellExecutor.execute( command.text )
}
}
Column {
anchors.centerIn: parentRect
spacing: 10
TextField {
id: command
height: 20
width: parentRect.width - 10
text: "echo `uname -a`"
}
Button {
id: runButton
width: command.width
text: "Remote run"
}
}
Полный код скрипта лежит тут
окошко выглядит вот так
С этим все просто.
Следующая часть - Файловая система.
Эта подсистема агента довольно большая и состоит из 3 основных частей:
1: Основа. В ее задаче содержать путь, по которому будет происходить работа остальных частей (это, грубо говоря то, что показывает PWD). Так же предоставляет свединия об объектах файловой системы: тип (диреткория/файл/устройство, время создания/доступа, etc)
От основы создаются/открываются файлы (вторая часть) и итераторы директории (3 часть)
2: Файл. Предоставляет доступ к файлу. Можно читать, писать, передвигать позицию чтения/записи, ограниченно можно сделать ioctl для открытого файла/устройства.
3: Итераторы директорий. Тут все просто. Открываем (или, лучше сказать, получаем) итератор и пробегаем им до конца директории, получая сведения об объектах.
Исполнение скрипта:
Для рассказа о том, как работать с FS сделаю простой примерчик.
Примерчик будет:
Писать некий скрипт в /tmp устройства
Ставить ему флажок исполнения (chmod +x)
Запускать его
В первом пункте мне поможет компонент FrClientFs, в остальных двух FrClientOS из описания выше.
Я просто изменю предыдущий пример, добавив в него FrClientFs и заменив TextField на TextArea:
- Код: Выделить всё
Item {
property string filePath: "/tmp/fsexample.sh" // так будет называться наш файл
id: shellExec
FrClientFs {
id: remoteFs
client: remoteClient
path: "/"
}
FrClientOS {
id: executor
client: remoteClient
}
Connections {
target: runButton
onClicked: shellExecutor.execute( command.text )
}
}
Column {
anchors.centerIn: parentRect
spacing: 10
TextArea {
id: command
height: parentRect.height - 40
width: parentRect.width - 10
text: "#!/bin/bash"
}
Button {
id: runButton
width: command.width
text: "Remote run"
}
}
Теперь на обработчике кнопки можно сделать 3 действия. Записать файл, сделать chmod, выполнить.
Оформлю это в отдельную функцию, потому как дальше сделаю еще кой чего.
- Код: Выделить всё
function runShell( )
{
remoteFs.writeFile( filePath, command.text )
executor.execute( "chmod +x " + filePath )
executor.execute( filePath )
}
функция writeFile из FrClientFs может записать в файл до 40килобайт. По-умолчанию пишет с 0 смещения, но смещение можно задать 2 параметром.
Далее 2 уже знакомых execute, который выполнят нужные команды.
Я немного переделал пример и теперь он будет спрашивать, нужно ли переписать файл, или удалить его, если таковой найден. Что получилось, см во вложении. Сам пример ТУТ пример небольшой и несложный. Думаю понятно, что там происходит.
===
Тут еще функции, которые есть у
FrClientFs:
exists( str ) - Проверяет найден ли файловый объект
mkdir( str ) - создает директорию
remove( str ) - удаляет файл или пустую директорию
removeAll( str ) - удаляет все рекурсивно
info( str ) - получить некоторую информацию про объект файловой системы:
Возвращает объект, который содержит свойства: exists - если объект найден, directory - если объект директория, empty - если объект пустая директория или файл, regular - если это обычный файл/директория, symlink - если это ссылка.
readFile( path, max, from = 0 ) - читает max байт (но не больше 40к) из файла по пути path, со смещения from
writeFile( path, data, from = 0 ) - пишет data (но не больше 40к) в файл по пути path, со смещения from. Возвращает количество записанных байт.
